Skip to content

Commit 6425da5

Browse files
author
Clement Champetier
committed
Merge branch 'develop' of https://github.com/mikrosimage/avTranscoder into dev_mediaPropertiesExceptionsPropertiesAsMap
2 parents d79d795 + 5f06065 commit 6425da5

23 files changed

+487
-107
lines changed

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,18 @@ codec=codecName
6565

6666
###### nosetests
6767
Python tests using nosetests.
68+
```
69+
cd test/pyTest
70+
nosetests
71+
```
6872

69-
Create environment variables to use your files in tests.
70-
* ```AVTRANSCODER_TEST_AUDIO_FILE```
73+
Some tests need environment variables to be executed (otherwise they will be skipped):
7174
* ```AVTRANSCODER_TEST_VIDEO_FILE```
75+
* ```AVTRANSCODER_TEST_AUDIO_WAVE_FILE```
76+
* ```AVTRANSCODER_TEST_AUDIO_MOV_FILE```
7277

7378
Note: for continuous integration, we launch tests with media files contained in ```avTranscoder-data``` repository.
7479

75-
Launch the tests:
76-
```
77-
cd test/pyTest
78-
nosetests
79-
```
8080

8181
#### Packaging
8282

cmake/FindFFmpeg.cmake

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,35 +32,39 @@ endmacro()
3232

3333

3434
### Macro: find_component
35-
#
36-
# Check the given component by invoking pkgconfig and
35+
#
36+
# Check the given component by invoking pkgconfig and
3737
# then looking up the libraries and include directories.
38-
# @todo: WIN and MAC OSX.
3938
#
4039
macro(find_component COMPONENT PKGCONFIG LIBRARY HEADER)
4140
if(NOT WIN32)
42-
# use pkg-config to get the directories and then use these values
43-
# in the FIND_PATH() and FIND_LIBRARY() calls
41+
# use pkg-config to get the directories
4442
find_package(PkgConfig)
4543
if(PKG_CONFIG_FOUND)
4644
pkg_check_modules(PC_${COMPONENT} ${PKGCONFIG})
4745
endif()
46+
# find include
47+
find_path(${COMPONENT}_INCLUDE_DIR
48+
${HEADER}
49+
HINTS ${PC_${COMPONENT}_INCLUDEDIR} ${PC_${COMPONENT}_INCLUDE_DIR}
50+
)
51+
# find lib
52+
find_library(${COMPONENT}_LIBRARIES
53+
NAMES ${LIBRARY}
54+
HINTS ${PC_${COMPONENT}_LIBDIR} ${PC_${COMPONENT}_LIBRARY_DIRS}
55+
)
56+
# set definition and version
57+
set(${COMPONENT}_DEFINITIONS ${PC_${COMPONENT}_CFLAGS_OTHER} CACHE STRING "The ${COMPONENT} CFLAGS.")
58+
set(${COMPONENT}_VERSION ${PC_${COMPONENT}_VERSION} CACHE STRING "The ${COMPONENT} version number.")
59+
else()
60+
# find include
61+
find_path(${COMPONENT}_INCLUDE_DIR ${HEADER})
62+
# find lib
63+
file(GLOB_RECURSE ${COMPONENT}_LIBRARIES "${CMAKE_PREFIX_PATH}/*${COMPONENT}.lib")
64+
# @todo: define definition and version
4865
endif()
4966

50-
find_path(${COMPONENT}_INCLUDE_DIR
51-
${HEADER}
52-
HINTS ${PC_${COMPONENT}_INCLUDEDIR} ${PC_${COMPONENT}_INCLUDE_DIR}
53-
)
54-
55-
find_library(${COMPONENT}_LIBRARIES
56-
NAMES ${LIBRARY}
57-
HINTS ${PC_${COMPONENT}_LIBDIR} ${PC_${COMPONENT}_LIBRARY_DIRS}
58-
)
59-
60-
set(${COMPONENT}_DEFINITIONS ${PC_${COMPONENT}_CFLAGS_OTHER} CACHE STRING "The ${COMPONENT} CFLAGS.")
61-
set(${COMPONENT}_VERSION ${PC_${COMPONENT}_VERSION} CACHE STRING "The ${COMPONENT} version number.")
62-
63-
# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIR is present.
67+
# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIR is present.
6468
if(${COMPONENT}_LIBRARIES AND ${COMPONENT}_INCLUDE_DIR)
6569
set(${COMPONENT}_FOUND TRUE)
6670
else()

src/AvTranscoder/codec/ICodec.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,17 @@ void ICodec::open()
6060
if( ret < 0 )
6161
{
6262
std::string msg = "unable open codec: ";
63-
msg += _avCodec->long_name;
64-
msg += " (";
65-
msg += _avCodec->name;
66-
msg += ") ";
63+
64+
if( _avCodec && _avCodec->long_name )
65+
msg += _avCodec->long_name;
66+
67+
if( _avCodec && _avCodec->name )
68+
{
69+
msg += " (";
70+
msg += _avCodec->name;
71+
msg += ") ";
72+
}
73+
6774
avcodec_close( _avCodecContext );
6875

6976
msg += getDescriptionFromErrorCode( ret );

src/AvTranscoder/decoder/AudioGenerator.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ AudioGenerator& AudioGenerator::operator=( const AudioGenerator& audioGenerator
2222
_inputFrame = NULL;
2323
_silent = NULL;
2424
_frameDesc = audioGenerator.getAudioFrameDesc();
25+
return *this;
2526
}
2627

2728
AudioGenerator::~AudioGenerator()

src/AvTranscoder/decoder/VideoGenerator.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ VideoGenerator& VideoGenerator::operator=( const VideoGenerator& videoGenerator
2424
_inputFrame = NULL;
2525
_blackImage = NULL;
2626
_frameDesc = videoGenerator.getVideoFrameDesc();
27+
return *this;
2728
}
2829

2930
VideoGenerator::~VideoGenerator()

src/AvTranscoder/frame/Frame.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Frame::Frame( const Frame& other )
2828
Frame& Frame::operator=( const Frame& other )
2929
{
3030
copyAVPacket( other.getAVPacket() );
31+
return *this;
3132
}
3233

3334
Frame::~Frame()

src/AvTranscoder/mediaProperty/AudioProperties.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,14 @@ size_t AudioProperties::getBitRate() const
159159
{
160160
if( ! _codecContext )
161161
throw std::runtime_error( "unknown codec context" );
162-
int bitsPerSample = av_get_bits_per_sample( _codecContext->codec_id );
163-
size_t bitRate = bitsPerSample ? _codecContext->sample_rate * _codecContext->channels * bitsPerSample : _codecContext->bit_rate;
164-
return bitRate;
162+
163+
// return bit rate of stream
164+
if( _codecContext->bit_rate )
165+
return _codecContext->bit_rate;
166+
167+
// else get computed bit rate from our computation (warning: way to compute bit rate of PCM audio data)
168+
int bitsPerSample = av_get_bits_per_sample( _codecContext->codec_id ); // 0 if unknown for the given codec
169+
return _codecContext->sample_rate * _codecContext->channels * bitsPerSample;
165170
}
166171

167172
size_t AudioProperties::getNbSamples() const

src/AvTranscoder/mediaProperty/AudioProperties.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ class AvExport AudioProperties
2828
size_t getCodecId() const;
2929
size_t getSampleRate() const;
3030
size_t getChannels() const;
31-
size_t getBitRate() const;
32-
size_t getNbSamples() const;
31+
size_t getBitRate() const; ///< 0 if unknown
32+
size_t getNbSamples() const; ///< 0 if unknown
3333

3434
size_t getTicksPerFrame() const;
3535
Rational getTimeBase() const;

src/AvTranscoder/mediaProperty/FileProperties.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class AvExport FileProperties
2929
size_t getProgramsCount() const;
3030
double getStartTime() const;
3131
double getDuration() const; ///< in seconds
32-
size_t getBitRate() const;
32+
size_t getBitRate() const; ///< total stream bitrate in bit/s, 0 if not available (result of a computation by ffmpeg)
3333
size_t getPacketSize() const;
3434

3535
PropertiesMap& getMetadatas() { return _metadatas; }

src/AvTranscoder/mediaProperty/VideoProperties.cpp

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,58 @@ size_t VideoProperties::getBitRate() const
395395
{
396396
if( ! _codecContext )
397397
throw std::runtime_error( "unknown codec context" );
398-
return _codecContext->bit_rate;
398+
// return bit rate of stream if present or VBR mode
399+
if( _codecContext->bit_rate || _codecContext->rc_max_rate )
400+
return _codecContext->bit_rate;
401+
402+
// else compute bit rate from the first GOP
403+
if( ! _formatContext || ! _codec )
404+
throw std::runtime_error( "cannot compute bit rate: unknown format or codec context" );
405+
406+
if( ! _codecContext->width || ! _codecContext->height )
407+
throw std::runtime_error( "cannot compute bit rate: invalid frame size" );
408+
409+
// discard no frame type when decode
410+
_codecContext->skip_frame = AVDISCARD_NONE;
411+
412+
#if LIBAVCODEC_VERSION_MAJOR > 54
413+
AVFrame* frame = av_frame_alloc();
414+
#else
415+
AVFrame* frame = avcodec_alloc_frame();
416+
#endif
417+
AVPacket pkt;
418+
av_init_packet( &pkt );
419+
avcodec_open2( _codecContext, _codec, NULL );
420+
421+
int gotFrame = 0;
422+
int count = 0;
423+
int gopFramesSize = 0;
424+
425+
while( ! av_read_frame( const_cast<AVFormatContext*>( _formatContext ), &pkt ) )
426+
{
427+
if( pkt.stream_index == (int)_streamIndex )
428+
{
429+
avcodec_decode_video2( _codecContext, frame, &gotFrame, &pkt );
430+
if( gotFrame )
431+
{
432+
gopFramesSize += frame->pkt_size;
433+
++count;
434+
}
435+
}
436+
av_free_packet( &pkt );
437+
if( _codecContext->gop_size == count )
438+
break;
439+
}
440+
#if LIBAVCODEC_VERSION_MAJOR > 54
441+
av_frame_free( &frame );
442+
#elif LIBAVCODEC_VERSION_MAJOR > 53
443+
avcodec_free_frame( &frame );
444+
#else
445+
av_free( frame );
446+
#endif
447+
448+
int bitsPerByte = 8;
449+
return (gopFramesSize / _codecContext->gop_size) * bitsPerByte * getFps();
399450
}
400451

401452
size_t VideoProperties::getMaxBitRate() const

src/AvTranscoder/transcoder/StreamTranscoder.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ bool StreamTranscoder::processRewrap()
342342
assert( _inputStream != NULL );
343343
assert( _outputStream != NULL );
344344

345-
LOG_INFO( "Rewrap a frame" )
345+
LOG_DEBUG( "Rewrap a frame" )
346346

347347
CodedData data;
348348
if( ! _inputStream->readNextPacket( data ) )
@@ -380,7 +380,7 @@ bool StreamTranscoder::processTranscode( const int subStreamIndex )
380380
assert( _frameBuffer != NULL );
381381
assert( _transform != NULL );
382382

383-
LOG_INFO( "Transcode a frame" )
383+
LOG_DEBUG( "Transcode a frame" )
384384

385385
// check offset
386386
if( _offset )

test/pyTest/testProperties.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import os
22

3+
# Check if environment is setup to run the tests
4+
if os.environ.get('AVTRANSCODER_TEST_AUDIO_WAVE_FILE') is None:
5+
from nose.plugins.skip import SkipTest
6+
raise SkipTest("Need to define environment variable AVTRANSCODER_TEST_AUDIO_WAVE_FILE")
7+
38
from nose.tools import *
49

510
from pyAvTranscoder import avtranscoder as av
611

712
av.preloadCodecsAndFormats()
13+
av.Logger.setLogLevel(av.AV_LOG_QUIET)
814

915

1016
def testAddMetadataDate():
@@ -17,7 +23,7 @@ def testAddMetadataDate():
1723
transcoder = av.Transcoder( ouputFile )
1824

1925
# rewrap a stream
20-
transcoder.add( os.environ['AVTRANSCODER_TEST_AUDIO_FILE'], 0, "")
26+
transcoder.add( os.environ['AVTRANSCODER_TEST_AUDIO_WAVE_FILE'], 0, "")
2127

2228
# add one metadata
2329
metadata_to_check = ("date", "value")
@@ -42,7 +48,7 @@ def testAddImpossibleMetadata():
4248
transcoder = av.Transcoder( ouputFile )
4349

4450
# rewrap a stream
45-
transcoder.add( os.environ['AVTRANSCODER_TEST_AUDIO_FILE'], 0, "")
51+
transcoder.add( os.environ['AVTRANSCODER_TEST_AUDIO_WAVE_FILE'], 0, "")
4652

4753
# add one metadata
4854
metadata_to_check = ("undefinedMetadataKey", "undefinedMetadataValue")

test/pyTest/testSetFrame.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import os
2-
31
from nose.tools import *
42

53
from pyAvTranscoder import avtranscoder as av
64

75
av.preloadCodecsAndFormats()
6+
av.Logger.setLogLevel(av.AV_LOG_QUIET)
87

98

109
def testSetVideoFrame():

test/pyTest/testTranscoderAdd.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
import os
22

3+
# Check if environment is setup to run the tests
4+
if os.environ.get('AVTRANSCODER_TEST_AUDIO_WAVE_FILE') is None:
5+
from nose.plugins.skip import SkipTest
6+
raise SkipTest("Need to define environment variable AVTRANSCODER_TEST_AUDIO_WAVE_FILE")
7+
38
from nose.tools import *
49

510
from pyAvTranscoder import avtranscoder as av
611

712
av.preloadCodecsAndFormats()
13+
av.Logger.setLogLevel(av.AV_LOG_QUIET)
814

915

1016
def testAddStreamTranscoder():
1117
"""
1218
Add a streamTranscoder to the Transcoder, and process rewrap of an audio stream.
1319
"""
1420
# input
15-
inputFile = av.InputFile( os.environ['AVTRANSCODER_TEST_AUDIO_FILE'] )
21+
inputFile = av.InputFile( os.environ['AVTRANSCODER_TEST_AUDIO_WAVE_FILE'] )
1622
inputIndex = 0
1723
inputFile.activateStream( inputIndex )
1824

test/pyTest/testTranscoderDummy.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from pyAvTranscoder import avtranscoder as av
44

55
av.preloadCodecsAndFormats()
6+
av.Logger.setLogLevel(av.AV_LOG_QUIET)
67

78

89
@raises(RuntimeError)

test/pyTest/testTranscoderNbFrames.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import os
2+
3+
# Check if environment is setup to run the tests
4+
if os.environ.get('AVTRANSCODER_TEST_VIDEO_FILE') is None:
5+
from nose.plugins.skip import SkipTest
6+
raise SkipTest("Need to define environment variable AVTRANSCODER_TEST_VIDEO_FILE")
7+
8+
from nose.tools import *
9+
10+
from pyAvTranscoder import avtranscoder as av
11+
12+
av.preloadCodecsAndFormats()
13+
av.Logger.setLogLevel(av.AV_LOG_QUIET)
14+
15+
16+
def testNbFramesVideoRewrap():
17+
"""
18+
Rewrap one video stream, check nb frames.
19+
"""
20+
inputFileName = os.environ['AVTRANSCODER_TEST_VIDEO_FILE']
21+
outputFileName = "testNbFramesVideoRewrap.mov"
22+
23+
ouputFile = av.OutputFile( outputFileName )
24+
transcoder = av.Transcoder( ouputFile )
25+
26+
transcoder.add( inputFileName, 0, "" )
27+
28+
progress = av.ConsoleProgress()
29+
transcoder.process( progress )
30+
31+
# get src file of rewrap
32+
src_inputFile = av.InputFile( inputFileName )
33+
src_properties = src_inputFile.getProperties()
34+
src_videoStream = src_properties.getVideoProperties()[0]
35+
36+
# get dst file of rewrap
37+
dst_inputFile = av.InputFile( outputFileName )
38+
dst_properties = dst_inputFile.getProperties()
39+
dst_videoStream = dst_properties.getVideoProperties()[0]
40+
41+
assert_equals( src_videoStream.getNbFrames(), dst_videoStream.getNbFrames() )
42+
43+
def testNbFramesVideoTranscode():
44+
"""
45+
Transcode one video stream (to h264), check nb frames.
46+
"""
47+
inputFileName = os.environ['AVTRANSCODER_TEST_VIDEO_FILE']
48+
outputFileName = "testNbFramesVideoTranscode.mov"
49+
50+
ouputFile = av.OutputFile( outputFileName )
51+
transcoder = av.Transcoder( ouputFile )
52+
53+
transcoder.add( inputFileName, 0, "mpeg2" )
54+
55+
progress = av.ConsoleProgress()
56+
transcoder.process( progress )
57+
58+
# get src file of transcode
59+
src_inputFile = av.InputFile( inputFileName )
60+
src_properties = src_inputFile.getProperties()
61+
src_videoStream = src_properties.getVideoProperties()[0]
62+
63+
# get dst file of transcode
64+
dst_inputFile = av.InputFile( outputFileName )
65+
dst_properties = dst_inputFile.getProperties()
66+
dst_videoStream = dst_properties.getVideoProperties()[0]
67+
68+
assert_equals( src_videoStream.getNbFrames(), dst_videoStream.getNbFrames() )

0 commit comments

Comments
 (0)