Skip to content

Commit 40da88a

Browse files
author
Clement Champetier
committed
OutputFile: use FormatContext instead of AVFormatContext
* Move some code from OutputFile to FormatContext.
1 parent 24eec82 commit 40da88a

File tree

5 files changed

+188
-142
lines changed

5 files changed

+188
-142
lines changed

src/AvTranscoder/file/InputFile.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ extern "C" {
1616
}
1717

1818
#include <stdexcept>
19-
#include <cassert>
2019

2120
namespace avtranscoder
2221
{

src/AvTranscoder/file/OutputFile.cpp

Lines changed: 41 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,124 +1,75 @@
11
#include "OutputFile.hpp"
22

3-
#include <AvTranscoder/option/Context.hpp>
4-
5-
extern "C" {
6-
#include <libavcodec/avcodec.h>
7-
#include <libavformat/avformat.h>
8-
}
9-
103
#include <iostream>
114
#include <stdexcept>
12-
#include <cassert>
135

146
namespace avtranscoder
157
{
168

179
OutputFile::OutputFile( const std::string& filename )
18-
: _formatContext ( NULL )
19-
, _outputFormat ( NULL )
20-
, _filename ( filename )
10+
: _formatContext( AV_OPT_FLAG_ENCODING_PARAM )
11+
, _outputStreams()
12+
, _frameCount()
13+
, _filename( filename )
2114
, _previousProcessedStreamDuration( 0.0 )
22-
, _verbose ( false )
23-
{
24-
if( ( _formatContext = avformat_alloc_context() ) == NULL )
25-
{
26-
throw std::runtime_error( "unable to create format context" );
27-
}
28-
}
15+
, _verbose( false )
16+
{}
2917

3018
bool OutputFile::setup()
3119
{
32-
av_register_all();
33-
if( ! _outputFormat )
34-
_outputFormat = av_guess_format( NULL, _filename.c_str(), NULL);
35-
36-
if( ! _outputFormat )
37-
{
38-
throw std::ios_base::failure( "unable to find format" );
39-
}
40-
41-
_formatContext->oformat = _outputFormat;
42-
43-
if( !( _outputFormat->flags & AVFMT_NOFILE ) )
44-
{
45-
if( avio_open2( &_formatContext->pb, _filename.c_str(), AVIO_FLAG_WRITE, NULL, NULL ) < 0 )
46-
{
47-
avformat_close_input( &_formatContext );
48-
_formatContext = NULL;
49-
throw std::ios_base::failure( "error when opening output format" );
50-
}
51-
}
52-
53-
return _formatContext != NULL;
20+
_formatContext.setOutputFormat( _filename );
21+
_formatContext.openRessource( _filename, AVIO_FLAG_WRITE );
22+
return true;
5423
}
5524

5625
IOutputStream& OutputFile::addVideoStream( const VideoCodec& videoDesc )
5726
{
58-
assert( _formatContext != NULL );
59-
60-
AVStream* stream = avformat_new_stream( _formatContext, videoDesc.getAVCodec() );
61-
if( stream == NULL )
62-
{
63-
throw std::runtime_error( "unable to add new video stream" );
64-
}
27+
AVStream& stream = _formatContext.addAVStream( *videoDesc.getAVCodec() );
6528

66-
stream->codec->width = videoDesc.getAVCodecContext()->width;
67-
stream->codec->height = videoDesc.getAVCodecContext()->height;
68-
stream->codec->bit_rate = videoDesc.getAVCodecContext()->bit_rate;
69-
stream->codec->pix_fmt = videoDesc.getAVCodecContext()->pix_fmt;
70-
stream->codec->profile = videoDesc.getAVCodecContext()->profile;
71-
stream->codec->level = videoDesc.getAVCodecContext()->level;
29+
stream.codec->width = videoDesc.getAVCodecContext()->width;
30+
stream.codec->height = videoDesc.getAVCodecContext()->height;
31+
stream.codec->bit_rate = videoDesc.getAVCodecContext()->bit_rate;
32+
stream.codec->pix_fmt = videoDesc.getAVCodecContext()->pix_fmt;
33+
stream.codec->profile = videoDesc.getAVCodecContext()->profile;
34+
stream.codec->level = videoDesc.getAVCodecContext()->level;
7235

7336
// need to set the time_base on the AVCodecContext and the AVStream
7437
// compensating the frame rate with the ticks_per_frame and keeping
7538
// a coherent reading speed.
7639
av_reduce(
77-
&stream->codec->time_base.num,
78-
&stream->codec->time_base.den,
40+
&stream.codec->time_base.num,
41+
&stream.codec->time_base.den,
7942
videoDesc.getAVCodecContext()->time_base.num * videoDesc.getAVCodecContext()->ticks_per_frame,
8043
videoDesc.getAVCodecContext()->time_base.den,
8144
INT_MAX );
8245

83-
stream->time_base = stream->codec->time_base;
46+
stream.time_base = stream.codec->time_base;
8447

85-
AvOutputStream* avOutputStream = new AvOutputStream( *this, _formatContext->nb_streams - 1 );
48+
AvOutputStream* avOutputStream = new AvOutputStream( *this, _formatContext.getNbStreams() - 1 );
8649
_outputStreams.push_back( avOutputStream );
8750

8851
return *_outputStreams.back();
8952
}
9053

9154
IOutputStream& OutputFile::addAudioStream( const AudioCodec& audioDesc )
9255
{
93-
assert( _formatContext != NULL );
56+
AVStream& stream = _formatContext.addAVStream( *audioDesc.getAVCodec() );
9457

95-
AVStream* stream = avformat_new_stream( _formatContext, audioDesc.getAVCodec() );
96-
if( stream == NULL )
97-
{
98-
throw std::runtime_error( "unable to add new audio stream" );
99-
}
58+
stream.codec->sample_rate = audioDesc.getAVCodecContext()->sample_rate;
59+
stream.codec->channels = audioDesc.getAVCodecContext()->channels;
60+
stream.codec->sample_fmt = audioDesc.getAVCodecContext()->sample_fmt;
10061

101-
stream->codec->sample_rate = audioDesc.getAVCodecContext()->sample_rate;
102-
stream->codec->channels = audioDesc.getAVCodecContext()->channels;
103-
stream->codec->sample_fmt = audioDesc.getAVCodecContext()->sample_fmt;
104-
105-
AvOutputStream* avOutputStream = new AvOutputStream( *this, _formatContext->nb_streams - 1 );
62+
AvOutputStream* avOutputStream = new AvOutputStream( *this, _formatContext.getNbStreams() - 1 );
10663
_outputStreams.push_back( avOutputStream );
10764

10865
return *_outputStreams.back();
10966
}
11067

11168
IOutputStream& OutputFile::addDataStream( const DataCodec& dataDesc )
11269
{
113-
assert( _formatContext != NULL );
114-
115-
AVStream* stream = avformat_new_stream( _formatContext, dataDesc.getAVCodec() );
116-
if( stream == NULL )
117-
{
118-
throw std::runtime_error( "unable to add new data stream" );
119-
}
70+
_formatContext.addAVStream( *dataDesc.getAVCodec() );
12071

121-
AvOutputStream* avOutputStream = new AvOutputStream( *this, _formatContext->nb_streams - 1 );
72+
AvOutputStream* avOutputStream = new AvOutputStream( *this, _formatContext.getNbStreams() - 1 );
12273
_outputStreams.push_back( avOutputStream );
12374

12475
return *_outputStreams.back();
@@ -133,15 +84,7 @@ IOutputStream& OutputFile::getStream( const size_t streamId )
13384

13485
bool OutputFile::beginWrap( )
13586
{
136-
int ret = avformat_write_header( _formatContext, NULL );
137-
if( ret != 0 )
138-
{
139-
char err[AV_ERROR_MAX_STRING_SIZE];
140-
av_strerror( ret, err, sizeof(err) );
141-
std::string msg = "could not write header: ";
142-
msg += err;
143-
throw std::runtime_error( msg );
144-
}
87+
_formatContext.writeHeader();
14588
_frameCount.clear();
14689
_frameCount.resize( _outputStreams.size(), 0 );
14790
return true;
@@ -165,26 +108,13 @@ IOutputStream::EWrappingStatus OutputFile::wrap( const CodedData& data, const si
165108
// packet.dts = _frameCount.at( streamId );
166109
// packet.pts = ;
167110

168-
// int ret = av_write_frame( _formatContext, &packet );
169-
int ret = av_interleaved_write_frame( _formatContext, &packet );
170-
171-
if( ret != 0 )
172-
{
173-
char err[AV_ERROR_MAX_STRING_SIZE];
174-
av_strerror( ret, err, sizeof(err) );
175-
std::string msg = "error when writting packet in stream: ";
176-
msg += err;
177-
// throw std::runtime_error( msg );
178-
std::cout << msg << std::endl;
179-
return IOutputStream::eWrappingError;
180-
}
111+
_formatContext.writeFrame( packet );
181112

182113
av_free_packet( &packet );
183114

184-
// get the current streams
185-
AVStream* currentStream = _formatContext->streams[ streamId ];
186-
// compute its duration
187-
double currentStreamDuration = (double)currentStream->cur_dts * currentStream->time_base.num / currentStream->time_base.den;
115+
// compute the duration of current stream
116+
AVStream& currentStream = _formatContext.getAVStream( streamId );
117+
double currentStreamDuration = (double)currentStream.cur_dts * currentStream.time_base.num / currentStream.time_base.den;
188118

189119
if( currentStreamDuration < _previousProcessedStreamDuration )
190120
{
@@ -200,18 +130,8 @@ IOutputStream::EWrappingStatus OutputFile::wrap( const CodedData& data, const si
200130

201131
bool OutputFile::endWrap( )
202132
{
203-
if( av_write_trailer( _formatContext ) != 0)
204-
{
205-
throw std::runtime_error( "could not write trailer" );
206-
}
207-
208-
if( !( _formatContext->oformat->flags & AVFMT_NOFILE ) )
209-
{
210-
avio_close( _formatContext->pb );
211-
}
212-
avformat_free_context( _formatContext );
213-
//freeFormat();
214-
133+
_formatContext.writeTrailer();
134+
_formatContext.closeRessource();
215135
return true;
216136
}
217137

@@ -225,13 +145,7 @@ void OutputFile::addMetadata( const PropertiesMap& dataMap )
225145

226146
void OutputFile::addMetadata( const std::string& key, const std::string& value )
227147
{
228-
int ret = av_dict_set( &_formatContext->metadata, key.c_str(), value.c_str(), 0 );
229-
if( ret < 0 )
230-
{
231-
char err[AV_ERROR_MAX_STRING_SIZE];
232-
av_strerror( ret, err, sizeof(err) );
233-
std::cout << err << std::endl;
234-
}
148+
_formatContext.addMetaData( key, value );
235149
}
236150

237151
void OutputFile::setProfile( const ProfileLoader::Profile& profile )
@@ -245,9 +159,8 @@ void OutputFile::setProfile( const ProfileLoader::Profile& profile )
245159
{
246160
throw std::runtime_error( "Invalid format according to the file extension." );
247161
}
248-
_outputFormat = av_guess_format( profile.find( constants::avProfileFormat )->second.c_str(), _filename.c_str(), NULL);
249162

250-
Context formatContext( _formatContext, AV_OPT_FLAG_ENCODING_PARAM );
163+
_formatContext.setOutputFormat( _filename, profile.find( constants::avProfileFormat )->second );
251164

252165
for( ProfileLoader::Profile::const_iterator it = profile.begin(); it != profile.end(); ++it )
253166
{
@@ -259,7 +172,7 @@ void OutputFile::setProfile( const ProfileLoader::Profile& profile )
259172

260173
try
261174
{
262-
Option& formatOption = formatContext.getOption( (*it).first );
175+
Option& formatOption = _formatContext.getOption( (*it).first );
263176
formatOption.setString( (*it).second );
264177
}
265178
catch( std::exception& e )
@@ -278,7 +191,7 @@ void OutputFile::setProfile( const ProfileLoader::Profile& profile )
278191

279192
try
280193
{
281-
Option& formatOption = formatContext.getOption( (*it).first );
194+
Option& formatOption = _formatContext.getOption( (*it).first );
282195
formatOption.setString( (*it).second );
283196
}
284197
catch( std::exception& e )
@@ -291,10 +204,10 @@ void OutputFile::setProfile( const ProfileLoader::Profile& profile )
291204

292205
double OutputFile::getProgressDuration()
293206
{
294-
if( _formatContext->nb_streams == 0 )
207+
if( _formatContext.getNbStreams() == 0 )
295208
throw std::runtime_error( "at least one stream must be set to get the progress duration" );
296-
AVStream* firstOutputStream = _formatContext->streams[0];
297-
return av_q2d( firstOutputStream->time_base ) * firstOutputStream->cur_dts;
209+
AVStream& firstOutputStream = _formatContext.getAVStream( 0 );
210+
return av_q2d( firstOutputStream.time_base ) * firstOutputStream.cur_dts;
298211
}
299212

300213
}

src/AvTranscoder/file/OutputFile.hpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,19 @@
22
#define _AV_TRANSCODER_FILE_OUTPUT_FILE_HPP_
33

44
#include <AvTranscoder/common.hpp>
5-
65
#include <AvTranscoder/mediaProperty/util.hpp>
6+
#include <AvTranscoder/option/FormatContext.hpp>
77

88
#include <AvTranscoder/codec/VideoCodec.hpp>
99
#include <AvTranscoder/codec/AudioCodec.hpp>
1010
#include <AvTranscoder/codec/DataCodec.hpp>
1111

1212
#include <AvTranscoder/codedStream/AvOutputStream.hpp>
13-
1413
#include <AvTranscoder/ProfileLoader.hpp>
1514

1615
#include <string>
1716
#include <vector>
1817

19-
struct AVOutputFormat;
20-
struct AVFormatContext;
21-
2218
namespace avtranscoder
2319
{
2420

@@ -110,16 +106,12 @@ class AvExport OutputFile
110106
virtual double getProgressDuration();
111107

112108
private:
109+
FormatContext _formatContext;
113110
std::vector<AvOutputStream*> _outputStreams; ///< Has ownership
114-
AVFormatContext* _formatContext; ///< Has ownership
115-
AVOutputFormat* _outputFormat; ///< Output format (has link, no ownership)
116-
117111
std::vector<size_t> _frameCount; ///< Number of wrapped frames
118112

119113
std::string _filename; ///< Output filename
120-
121114
double _previousProcessedStreamDuration; ///< To manage process streams order
122-
123115
bool _verbose;
124116
};
125117

0 commit comments

Comments
 (0)