Skip to content

Commit 0f285b2

Browse files
committed
Merge pull request #201 from cchampet/dev_addTestsForProcessStat
Added pyTests to check ProcessStat Appveyor: up ffmpeg version to v2.4.5
2 parents 6419a2d + c488619 commit 0f285b2

18 files changed

+234
-60
lines changed

INSTALL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ AvTranscoder uses CMake as build system.
44

55
#### Dependencies
66
AvTranscoder can depend on ffmpeg, libav, or any fork of these projects that follow the same API.
7-
* Recommended ffmpeg versions: 2.2.11, 2.4.2, 2.5.7
7+
* Recommended ffmpeg versions: 2.4.2, 2.4.5, 2.5.7
88
* Recommended libav versions: 11.3
99

1010
#### To build

appveyor.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ platform:
55
- x86
66
# - x64
77

8+
environment:
9+
FFMPEG_VERSION: 2.4.5
10+
811
matrix:
912
fast_finish: true
1013

src/AvTranscoder/file/InputFile.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,16 @@ namespace avtranscoder
2222

2323
InputFile::InputFile(const std::string& filename)
2424
: _formatContext(filename, AV_OPT_FLAG_DECODING_PARAM)
25-
, _properties(_formatContext)
25+
, _properties(NULL)
2626
, _filename(filename)
2727
, _inputStreams()
2828
{
29+
// Fill the FormatContext with the stream information
2930
_formatContext.findStreamInfo();
3031

32+
// Get the stream information as properties
33+
_properties = new FileProperties(_formatContext);
34+
3135
// Create streams
3236
for(size_t streamIndex = 0; streamIndex < _formatContext.getNbStreams(); ++streamIndex)
3337
{
@@ -37,6 +41,7 @@ InputFile::InputFile(const std::string& filename)
3741

3842
InputFile::~InputFile()
3943
{
44+
delete _properties;
4045
for(std::vector<InputStream*>::iterator it = _inputStreams.begin(); it != _inputStreams.end(); ++it)
4146
{
4247
delete(*it);
@@ -45,7 +50,7 @@ InputFile::~InputFile()
4550

4651
void InputFile::analyse(IProgress& progress, const EAnalyseLevel level)
4752
{
48-
_properties.extractStreamProperties(progress, level);
53+
_properties->extractStreamProperties(progress, level);
4954
}
5055

5156
FileProperties InputFile::analyseFile(const std::string& filename, IProgress& progress, const EAnalyseLevel level)
@@ -160,8 +165,8 @@ std::string InputFile::getFormatMimeType() const
160165
double InputFile::getFps()
161166
{
162167
double fps = 1;
163-
if(_properties.getNbVideoStreams())
164-
fps = _properties.getVideoProperties().at(0).getFps();
168+
if(_properties->getNbVideoStreams())
169+
fps = _properties->getVideoProperties().at(0).getFps();
165170
return fps;
166171
}
167172

src/AvTranscoder/file/InputFile.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class AvExport InputFile
6868
* @note require to launch analyse() before to fill the property struture
6969
* @return structure of media metadatas
7070
**/
71-
const FileProperties& getProperties() const { return _properties; }
71+
const FileProperties& getProperties() const { return *_properties; }
7272

7373
/**
7474
* @brief Get stream type: video, audio, subtitle, etc.
@@ -121,7 +121,7 @@ class AvExport InputFile
121121

122122
protected:
123123
FormatContext _formatContext;
124-
FileProperties _properties;
124+
FileProperties* _properties;
125125
std::string _filename;
126126
std::vector<InputStream*> _inputStreams; ///< Has ownership
127127
};

src/AvTranscoder/stat/AudioStat.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ class AvExport AudioStat
1919
}
2020

2121
public:
22+
float getDuration() const { return _duration; }
23+
size_t getNbPackets() const { return _nbPackets; }
24+
25+
private:
2226
float _duration;
2327
size_t _nbPackets;
2428
};

src/AvTranscoder/stat/VideoStat.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
namespace avtranscoder
66
{
77

8-
double VideoStat::psnr(const double d)
8+
double VideoStat::toPSNR(const double mse)
99
{
10-
return -10.0 * log10(d);
10+
return -10.0 * log10(mse);
1111
}
1212
}

src/AvTranscoder/stat/VideoStat.hpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,18 @@ class AvExport VideoStat
2121
}
2222

2323
public:
24-
static double psnr(const double d);
24+
float getDuration() const { return _duration; }
25+
size_t getNbFrames() const { return _nbFrames; }
26+
size_t getQuality() const { return _quality; }
27+
double getPSNR() const { return _psnr; }
2528

26-
public:
29+
void setQuality(const size_t quality) { _quality = quality; }
30+
void setPSNR(const double mse) { _psnr = VideoStat::toPSNR(mse); }
31+
32+
private:
33+
static double toPSNR(const double mse);
34+
35+
private:
2736
float _duration;
2837
size_t _nbFrames;
2938
size_t _quality; ///< Between 1 (good) and FF_LAMBDA_MAX (bad). 0 if unknown.

src/AvTranscoder/stat/stat.i

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
%{
2-
#include <AvTranscoder/stat/ProcessStat.hpp>
32
#include <AvTranscoder/stat/VideoStat.hpp>
43
#include <AvTranscoder/stat/AudioStat.hpp>
4+
#include <AvTranscoder/stat/ProcessStat.hpp>
55
%}
66

7-
%include <AvTranscoder/stat/ProcessStat.hpp>
87
%include <AvTranscoder/stat/VideoStat.hpp>
98
%include <AvTranscoder/stat/AudioStat.hpp>
9+
%include <AvTranscoder/stat/ProcessStat.hpp>

src/AvTranscoder/transcoder/Transcoder.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -580,9 +580,9 @@ void Transcoder::fillProcessStat(ProcessStat& processStat)
580580
const AVCodecContext& encoderContext = encoder->getCodec().getAVCodecContext();
581581
if(encoderContext.coded_frame && (encoderContext.flags & CODEC_FLAG_PSNR))
582582
{
583-
videoStat._quality = encoderContext.coded_frame->quality;
584-
videoStat._psnr = VideoStat::psnr(encoderContext.coded_frame->error[0] /
585-
(encoderContext.width * encoderContext.height * 255.0 * 255.0));
583+
videoStat.setQuality(encoderContext.coded_frame->quality);
584+
videoStat.setPSNR(encoderContext.coded_frame->error[0] /
585+
(encoderContext.width * encoderContext.height * 255.0 * 255.0));
586586
}
587587
}
588588
processStat.addVideoStat(streamIndex, videoStat);

test/pyTest/testInputFile.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import os
2+
3+
# Check if environment is setup to run the tests
4+
if os.environ.get('AVTRANSCODER_TEST_VIDEO_MOV_FILE') is None:
5+
from nose.plugins.skip import SkipTest
6+
raise SkipTest("Need to define environment variables "
7+
"AVTRANSCODER_TEST_VIDEO_MOV_FILE")
8+
9+
from nose.tools import *
10+
11+
from pyAvTranscoder import avtranscoder as av
12+
13+
14+
@raises(IOError)
15+
def testCreateInputFileFromUnexistingFilename():
16+
"""
17+
Create an InputFile from an unexisting filename.
18+
"""
19+
inputFileName = "testCreateInputFileFromUnexistingFilename"
20+
av.InputFile( inputFileName )
21+
22+
23+
def testInputFileAnalyseFirstGop():
24+
"""
25+
Analyse the first gop of an InputFile, and check if the correct attributes are filled.
26+
"""
27+
inputFileName = os.environ['AVTRANSCODER_TEST_VIDEO_MOV_FILE']
28+
inputFile = av.InputFile( inputFileName )
29+
30+
# The analyse of the first GOP is not done yet
31+
videoProperties = inputFile.getProperties().getVideoProperties()[0]
32+
assert_equals(videoProperties.isInterlaced(), False)
33+
assert_equals(videoProperties.isTopFieldFirst(), False)
34+
assert_equals(videoProperties.getGopStructure(), ())
35+
36+
# Analyse first GOP
37+
progress = av.NoDisplayProgress()
38+
inputFile.analyse( progress, av.eAnalyseLevelFirstGop )
39+
40+
# Check properties after GOP analysis
41+
videoProperties = inputFile.getProperties().getVideoProperties()[0]
42+
assert_not_equals(videoProperties.getGopStructure(), ())

test/pyTest/testProcessStat.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import os
2+
3+
# Check if environment is setup to run the tests
4+
if os.environ.get('AVTRANSCODER_TEST_VIDEO_AVI_FILE') is None:
5+
from nose.plugins.skip import SkipTest
6+
raise SkipTest("Need to define environment variables "
7+
"AVTRANSCODER_TEST_VIDEO_AVI_FILE")
8+
9+
from nose.tools import *
10+
11+
from pyAvTranscoder import avtranscoder as av
12+
13+
14+
def testProcessWithStatistics():
15+
"""
16+
Process one video stream with a custom profile of encoding to activate statistics.
17+
"""
18+
inputFileName = os.environ['AVTRANSCODER_TEST_VIDEO_AVI_FILE']
19+
outputFileName = "testProcessWithStatistics.mov"
20+
21+
ouputFile = av.OutputFile( outputFileName )
22+
transcoder = av.Transcoder( ouputFile )
23+
24+
# create custom profile
25+
customProfile = av.ProfileMap()
26+
customProfile[av.avProfileIdentificator] = "customProfile"
27+
customProfile[av.avProfileIdentificatorHuman] = "custom profile"
28+
customProfile[av.avProfileType] = av.avProfileTypeVideo
29+
customProfile[av.avProfileCodec] = "mpeg2video"
30+
customProfile[av.avProfileProcessStat] = "processStat"
31+
32+
src_inputFile = av.InputFile( inputFileName )
33+
src_properties = src_inputFile.getProperties()
34+
src_videoStream = src_properties.getVideoProperties()[0]
35+
videoStreamIndex = src_videoStream.getStreamIndex()
36+
transcoder.add( inputFileName, videoStreamIndex, customProfile )
37+
38+
progress = av.ConsoleProgress()
39+
processStat = transcoder.process( progress )
40+
41+
# check process stat returned
42+
videoStat = processStat.getVideoStat(0)
43+
assert_equals(videoStat.getDuration(), src_videoStream.getDuration())
44+
assert_equals(videoStat.getNbFrames(), int(src_videoStream.getDuration() * src_videoStream.getFps()))
45+
assert_not_equals(videoStat.getQuality(), 0)
46+
assert_not_equals(videoStat.getPSNR(), 0)

test/pyTest/testTranscoderRewrap.py

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ def checkStream(src_stream, dst_stream):
4545
continue
4646
assert_equals( src_propertiesMap[key], dst_propertiesMap[key] )
4747

48+
def checkVideoStat(src_videoStream, dst_videoStat):
49+
"""
50+
Check the values of the video process stats returned after a process.
51+
@note Because the process does not include a profile with "processStat", output quality and PSNR are not set.
52+
"""
53+
assert_equals(dst_videoStat.getDuration(), src_videoStream.getDuration())
54+
assert_equals(dst_videoStat.getNbFrames(), int(src_videoStream.getDuration() * src_videoStream.getFps()))
55+
assert_equals(dst_videoStat.getQuality(), 0)
56+
assert_equals(dst_videoStat.getPSNR(), 0)
57+
4858

4959
def testRewrapAudioStream():
5060
"""
@@ -53,8 +63,6 @@ def testRewrapAudioStream():
5363
# get src file of wrap
5464
inputFileName = os.environ['AVTRANSCODER_TEST_AUDIO_WAVE_FILE']
5565
src_inputFile = av.InputFile( inputFileName )
56-
progress = av.NoDisplayProgress()
57-
src_inputFile.analyse( progress )
5866
src_properties = src_inputFile.getProperties()
5967
src_audioStream = src_properties.getAudioProperties()[0]
6068

@@ -64,11 +72,15 @@ def testRewrapAudioStream():
6472

6573
transcoder = av.Transcoder( ouputFile )
6674
transcoder.add( inputFileName, 0 )
67-
transcoder.process( progress )
75+
progress = av.NoDisplayProgress()
76+
processStat = transcoder.process( progress )
77+
78+
# check process stat returned
79+
audioStat = processStat.getAudioStat(0)
80+
assert_equals(src_audioStream.getDuration(), audioStat.getDuration())
6881

6982
# get dst file of wrap
7083
dst_inputFile = av.InputFile( outputFileName )
71-
dst_inputFile.analyse( progress, av.eAnalyseLevelHeader )
7284
dst_properties = dst_inputFile.getProperties()
7385
dst_audioStream = dst_properties.getAudioProperties()[0]
7486

@@ -86,8 +98,6 @@ def testRewrapAVIVideoStream():
8698
# get src file of wrap
8799
inputFileName = os.environ['AVTRANSCODER_TEST_VIDEO_AVI_FILE']
88100
src_inputFile = av.InputFile( inputFileName )
89-
progress = av.NoDisplayProgress()
90-
src_inputFile.analyse( progress )
91101
src_properties = src_inputFile.getProperties()
92102
src_videoStream = src_properties.getVideoProperties()[0]
93103

@@ -97,11 +107,14 @@ def testRewrapAVIVideoStream():
97107

98108
transcoder = av.Transcoder( ouputFile )
99109
transcoder.add( inputFileName, 0 )
100-
transcoder.process( progress )
110+
progress = av.NoDisplayProgress()
111+
processStat = transcoder.process( progress )
112+
113+
# check process stat returned
114+
checkVideoStat(src_videoStream, processStat.getVideoStat(0))
101115

102116
# get dst file of wrap
103117
dst_inputFile = av.InputFile( outputFileName )
104-
dst_inputFile.analyse( progress )
105118
dst_properties = dst_inputFile.getProperties()
106119
dst_videoStream = dst_properties.getVideoProperties()[0]
107120

@@ -119,8 +132,6 @@ def testRewrapMOVVideoStream():
119132
# get src file of wrap
120133
inputFileName = os.environ['AVTRANSCODER_TEST_VIDEO_MOV_FILE']
121134
src_inputFile = av.InputFile( inputFileName )
122-
progress = av.NoDisplayProgress()
123-
src_inputFile.analyse( progress )
124135
src_properties = src_inputFile.getProperties()
125136
src_videoStream = src_properties.getVideoProperties()[0]
126137

@@ -130,11 +141,14 @@ def testRewrapMOVVideoStream():
130141

131142
transcoder = av.Transcoder( ouputFile )
132143
transcoder.add( inputFileName, 1 )
133-
transcoder.process( progress )
144+
progress = av.NoDisplayProgress()
145+
processStat = transcoder.process( progress )
146+
147+
# check process stat returned
148+
checkVideoStat(src_videoStream, processStat.getVideoStat(0))
134149

135150
# get dst file of wrap
136151
dst_inputFile = av.InputFile( outputFileName )
137-
dst_inputFile.analyse( progress )
138152
dst_properties = dst_inputFile.getProperties()
139153
dst_videoStream = dst_properties.getVideoProperties()[0]
140154

test/pyTest/testTranscoderTranscodeAudioMov.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,16 @@ def testTranscodeMovVariableNbSamplesPerFrame():
3030
customProfile[av.avProfileCodec] = "pcm_s24le"
3131

3232
inputFile = av.InputFile( inputFileName )
33-
audioStreamIndex = inputFile.getProperties().getAudioProperties()[0].getStreamIndex()
33+
src_audioStream = inputFile.getProperties().getAudioProperties()[0]
34+
audioStreamIndex = src_audioStream.getStreamIndex()
3435
transcoder.add( inputFileName, audioStreamIndex, customProfile )
3536

3637
progress = av.ConsoleProgress()
37-
transcoder.process( progress )
38+
processStat = transcoder.process( progress )
39+
40+
# check process stat returned
41+
audioStat = processStat.getAudioStat(0)
42+
assert_equals(src_audioStream.getDuration(), audioStat.getDuration())
3843

3944
# get dst file of transcode
4045
dst_inputFile = av.InputFile( outputFileName )
@@ -44,4 +49,3 @@ def testTranscodeMovVariableNbSamplesPerFrame():
4449

4550
assert_equals( "pcm_s24le", dst_audioStream.getCodecName() )
4651
assert_equals( "PCM signed 24-bit little-endian", dst_audioStream.getCodecLongName() )
47-

0 commit comments

Comments
 (0)