Skip to content

Commit 94b6a4d

Browse files
committed
Merge branch 'develop' into fix_gopAnalysisOfRawStream
2 parents edc9345 + f3b6f44 commit 94b6a4d

File tree

10 files changed

+127
-96
lines changed

10 files changed

+127
-96
lines changed

src/AvTranscoder/data/decoded/Frame.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ Frame::~Frame()
4040
}
4141
}
4242

43+
int Frame::getEncodedSize() const
44+
{
45+
return av_frame_get_pkt_size(_frame);
46+
}
47+
4348
void Frame::copyData(const Frame& frameToRef)
4449
{
4550
const int ret = av_frame_copy(_frame, &frameToRef.getAVFrame());

src/AvTranscoder/data/decoded/Frame.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ class AvExport Frame
4343
*/
4444
int* getLineSize() const { return _frame->linesize; }
4545

46+
/**
47+
* @return Size of the corresponding packet containing the compressed frame (in bytes)
48+
* @warning returns a negative value if the size is unknown
49+
*/
50+
int getEncodedSize() const;
51+
4652
/**
4753
* @brief Copy the data of the given Frame.
4854
* @note This function does not allocate anything: the current frame must be already initialized and

src/AvTranscoder/file/FormatContext.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ FormatContext::~FormatContext()
5353

5454
void FormatContext::findStreamInfo(AVDictionary** options)
5555
{
56-
int err = avformat_find_stream_info(_avFormatContext, options);
56+
const int err = avformat_find_stream_info(_avFormatContext, options);
5757
if(err < 0)
5858
{
5959
throw std::ios_base::failure("Unable to find stream informations: " + getDescriptionFromErrorCode(err));
@@ -65,7 +65,7 @@ void FormatContext::openRessource(const std::string& url, int flags)
6565
if((_avFormatContext->flags & AVFMT_NOFILE) == AVFMT_NOFILE)
6666
return;
6767

68-
int err = avio_open2(&_avFormatContext->pb, url.c_str(), flags, NULL, NULL);
68+
const int err = avio_open2(&_avFormatContext->pb, url.c_str(), flags, NULL, NULL);
6969
if(err < 0)
7070
{
7171
throw std::ios_base::failure("Error when opening output format: " + getDescriptionFromErrorCode(err));
@@ -77,7 +77,7 @@ void FormatContext::closeRessource()
7777
if((_avFormatContext->flags & AVFMT_NOFILE) == AVFMT_NOFILE)
7878
return;
7979

80-
int err = avio_close(_avFormatContext->pb);
80+
const int err = avio_close(_avFormatContext->pb);
8181
if(err < 0)
8282
{
8383
throw std::ios_base::failure("Error when close output format: " + getDescriptionFromErrorCode(err));
@@ -86,7 +86,7 @@ void FormatContext::closeRessource()
8686

8787
void FormatContext::writeHeader(AVDictionary** options)
8888
{
89-
int ret = avformat_write_header(_avFormatContext, options);
89+
const int ret = avformat_write_header(_avFormatContext, options);
9090
if(ret != 0)
9191
{
9292
throw std::runtime_error("Could not write header: " + getDescriptionFromErrorCode(ret));
@@ -115,7 +115,7 @@ void FormatContext::writeFrame(AVPacket& packet, bool interleaved)
115115

116116
void FormatContext::writeTrailer()
117117
{
118-
int ret = av_write_trailer(_avFormatContext);
118+
const int ret = av_write_trailer(_avFormatContext);
119119
if(ret != 0)
120120
{
121121
throw std::runtime_error("Could not write trailer: " + getDescriptionFromErrorCode(ret));
@@ -124,7 +124,7 @@ void FormatContext::writeTrailer()
124124

125125
void FormatContext::addMetaData(const std::string& key, const std::string& value)
126126
{
127-
int ret = av_dict_set(&_avFormatContext->metadata, key.c_str(), value.c_str(), 0);
127+
const int ret = av_dict_set(&_avFormatContext->metadata, key.c_str(), value.c_str(), 0);
128128
if(ret < 0)
129129
{
130130
LOG_ERROR(getDescriptionFromErrorCode(ret))
@@ -144,8 +144,8 @@ AVStream& FormatContext::addAVStream(const AVCodec& avCodec)
144144

145145
bool FormatContext::seek(const uint64_t position, const int flag)
146146
{
147-
LOG_INFO("Seek in '" << _avFormatContext->filename << "' at " << position << " (in AV_TIME_BASE units)")
148-
int err = av_seek_frame(_avFormatContext, -1, position, flag);
147+
LOG_INFO("Seek in '" << _avFormatContext->filename << "' at " << position << " with flag '"<< flag << "'")
148+
const int err = av_seek_frame(_avFormatContext, -1, position, flag);
149149
if(err < 0)
150150
{
151151
LOG_ERROR("Error when seek at " << position << " (in AV_TIME_BASE units) in file")

src/AvTranscoder/properties/FileProperties.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -160,15 +160,10 @@ bool FileProperties::isRawFormat() const
160160
std::string FileProperties::getFormatMimeType() const
161161
{
162162
#if LIBAVFORMAT_VERSION_MAJOR <= 55
163-
LOG_WARN("Cannot get mime type format of '" << getFilename()
164-
<< "' because your libavformat library has a major version <= 55.")
165-
return "not available";
163+
throw std::runtime_error("cannot get mime type format: libavformat library has a major version <= 55.");
166164
#else
167165
if(_avFormatContext->iformat->mime_type == NULL)
168-
{
169-
LOG_WARN("Unknown demuxer format mime type of '" << getFilename() << "'.")
170-
return "";
171-
}
166+
throw std::runtime_error("Unknown demuxer format mime type");
172167
return std::string(_avFormatContext->iformat->mime_type);
173168
#endif
174169
}
@@ -247,6 +242,7 @@ PropertyVector& FileProperties::fillVector(PropertyVector& data) const
247242
addProperty(data, "filename", &FileProperties::getFilename);
248243
addProperty(data, "formatName", &FileProperties::getFormatName);
249244
addProperty(data, "formatLongName", &FileProperties::getFormatLongName);
245+
addProperty(data, "mimeType", &FileProperties::getFormatMimeType);
250246

251247
addProperty(data, "startTime", &FileProperties::getStartTime);
252248
addProperty(data, "duration", &FileProperties::getDuration);

src/AvTranscoder/properties/PixelProperties.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ PropertyVector& PixelProperties::fillVector(PropertyVector& data) const
274274
}
275275
catch(const std::exception& e)
276276
{
277-
detail::add(data, "colorComponents", e.what());
277+
detail::add(data, "colorComponents", detail::propertyValueIfError);
278278
}
279279

280280
try

src/AvTranscoder/properties/VideoProperties.cpp

Lines changed: 67 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "VideoProperties.hpp"
22

3+
#include <AvTranscoder/data/decoded/Frame.hpp>
34
#include <AvTranscoder/properties/util.hpp>
45
#include <AvTranscoder/progress/NoDisplayProgress.hpp>
56

@@ -19,9 +20,11 @@ namespace avtranscoder
1920
VideoProperties::VideoProperties(const FormatContext& formatContext, const size_t index, IProgress& progress,
2021
const EAnalyseLevel level)
2122
: StreamProperties(formatContext, index)
23+
, _levelAnalysis(level)
2224
, _pixelProperties()
2325
, _isInterlaced(false)
2426
, _isTopFieldFirst(false)
27+
, _gopSize(0)
2528
, _gopStructure()
2629
, _firstGopTimeCode(-1)
2730
{
@@ -31,7 +34,7 @@ VideoProperties::VideoProperties(const FormatContext& formatContext, const size_
3134
_firstGopTimeCode = _codecContext->timecode_frame_start;
3235
}
3336

34-
if(level == eAnalyseLevelFirstGop)
37+
if(_levelAnalysis == eAnalyseLevelFirstGop)
3538
analyseGopStructure(progress);
3639
}
3740

@@ -43,11 +46,8 @@ std::string VideoProperties::getProfileName() const
4346
if(_codec->capabilities & CODEC_CAP_TRUNCATED)
4447
_codecContext->flags |= CODEC_FLAG_TRUNCATED;
4548

46-
if(_codecContext->profile == -99)
47-
throw std::runtime_error("unknown codec profile");
48-
4949
const char* profile = NULL;
50-
if((profile = av_get_profile_name(_codec, _codecContext->profile)) == NULL)
50+
if((profile = av_get_profile_name(_codec, getProfile())) == NULL)
5151
throw std::runtime_error("unknown codec profile");
5252

5353
return std::string(profile);
@@ -333,51 +333,44 @@ size_t VideoProperties::getBitRate() const
333333
if(!_codecContext->width || !_codecContext->height)
334334
throw std::runtime_error("cannot compute bit rate: invalid frame size");
335335

336+
// Needed to get the gop size
337+
if(_levelAnalysis < eAnalyseLevelFirstGop)
338+
throw std::runtime_error("cannot compute bit rate: need to get info from the first gop (see eAnalyseLevelFirstGop)");
339+
336340
// discard no frame type when decode
337341
_codecContext->skip_frame = AVDISCARD_NONE;
338342

339-
#if LIBAVCODEC_VERSION_MAJOR > 54
340-
AVFrame* frame = av_frame_alloc();
341-
#else
342-
AVFrame* frame = avcodec_alloc_frame();
343-
#endif
343+
Frame frame;
344344
AVPacket pkt;
345345
av_init_packet(&pkt);
346346
avcodec_open2(_codecContext, _codec, NULL);
347347

348348
int gotFrame = 0;
349-
int count = 0;
349+
size_t count = 0;
350350
int gopFramesSize = 0;
351351

352352
while(!av_read_frame(const_cast<AVFormatContext*>(_formatContext), &pkt))
353353
{
354354
if(pkt.stream_index == (int)_streamIndex)
355355
{
356-
avcodec_decode_video2(_codecContext, frame, &gotFrame, &pkt);
356+
avcodec_decode_video2(_codecContext, &frame.getAVFrame(), &gotFrame, &pkt);
357357
if(gotFrame)
358358
{
359359
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(54, 7, 100)
360-
gopFramesSize += av_frame_get_pkt_size(frame);
360+
gopFramesSize += frame.getEncodedSize();
361361
#else
362362
gopFramesSize += pkt.size;
363363
#endif
364364
++count;
365365
}
366366
}
367367
av_free_packet(&pkt);
368-
if(_codecContext->gop_size == count)
368+
if(getGopSize() == count)
369369
break;
370370
}
371-
#if LIBAVCODEC_VERSION_MAJOR > 54
372-
av_frame_free(&frame);
373-
#elif LIBAVCODEC_VERSION_MAJOR > 53
374-
avcodec_free_frame(&frame);
375-
#else
376-
av_free(frame);
377-
#endif
378371

379372
int bitsPerByte = 8;
380-
return (gopFramesSize / _codecContext->gop_size) * bitsPerByte * getFps();
373+
return (gopFramesSize / getGopSize()) * bitsPerByte * getFps();
381374
}
382375

383376
size_t VideoProperties::getMaxBitRate() const
@@ -425,13 +418,6 @@ size_t VideoProperties::getHeight() const
425418
return _codecContext->height;
426419
}
427420

428-
size_t VideoProperties::getGopSize() const
429-
{
430-
if(!_codecContext)
431-
throw std::runtime_error("unknown codec context");
432-
return _codecContext->gop_size;
433-
}
434-
435421
size_t VideoProperties::getDtgActiveFormat() const
436422
{
437423
if(!_codecContext)
@@ -493,61 +479,55 @@ void VideoProperties::analyseGopStructure(IProgress& progress)
493479
AVPacket pkt;
494480
av_init_packet(&pkt);
495481

496-
// Allocate frame
497-
#if LIBAVCODEC_VERSION_MAJOR > 54
498-
AVFrame* frame = av_frame_alloc();
499-
#else
500-
AVFrame* frame = avcodec_alloc_frame();
501-
#endif
502-
503482
// Initialize the AVCodecContext to use the given AVCodec
504483
avcodec_open2(_codecContext, _codec, NULL);
505484

506-
int count = 0;
485+
Frame frame;
486+
size_t count = 0;
507487
int gotFrame = 0;
508-
bool stopAnalyse = false;
488+
int positionOfFirstKeyFrame = -1;
489+
int positionOfLastKeyFrame = -1;
509490

510491
while(!av_read_frame(const_cast<AVFormatContext*>(_formatContext), &pkt))
511492
{
512493
if(pkt.stream_index == (int)_streamIndex)
513494
{
514-
avcodec_decode_video2(_codecContext, frame, &gotFrame, &pkt);
495+
avcodec_decode_video2(_codecContext, &frame.getAVFrame(), &gotFrame, &pkt);
515496
if(gotFrame)
516497
{
498+
AVFrame& avFrame = frame.getAVFrame();
499+
517500
_gopStructure.push_back(
518-
std::make_pair(av_get_picture_type_char(frame->pict_type), frame->key_frame));
519-
_isInterlaced = frame->interlaced_frame;
520-
_isTopFieldFirst = frame->top_field_first;
501+
std::make_pair(av_get_picture_type_char(avFrame.pict_type), frame.getEncodedSize()));
502+
_isInterlaced = avFrame.interlaced_frame;
503+
_isTopFieldFirst = avFrame.top_field_first;
504+
if(avFrame.pict_type == AV_PICTURE_TYPE_I)
505+
{
506+
if(positionOfFirstKeyFrame == -1)
507+
positionOfFirstKeyFrame = count;
508+
else
509+
positionOfLastKeyFrame = count;
510+
}
511+
521512
++count;
522-
if(progress.progress(count, _codecContext->gop_size) == eJobStatusCancel)
523-
stopAnalyse = true;
524513
}
525514
}
526-
527515
av_free_packet(&pkt);
528516

529-
if(_codecContext->gop_size == count)
517+
// If the first 2 key frames are found
518+
if(positionOfFirstKeyFrame != -1 && positionOfLastKeyFrame != -1)
530519
{
531-
stopAnalyse = true;
532-
}
533-
534-
if(stopAnalyse)
520+
// Set gop size as distance between these 2 key frames
521+
_gopSize = positionOfLastKeyFrame - positionOfFirstKeyFrame;
522+
// Update gop structure to keep only one gop
523+
while(_gopStructure.size() > _gopSize)
524+
_gopStructure.pop_back();
535525
break;
526+
}
536527
}
537528

538529
// Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext itself)
539530
avcodec_close(_codecContext);
540-
541-
// Free frame
542-
#if LIBAVCODEC_VERSION_MAJOR > 54
543-
av_frame_free(&frame);
544-
#else
545-
#if LIBAVCODEC_VERSION_MAJOR > 53
546-
avcodec_free_frame(&frame);
547-
#else
548-
av_free(frame);
549-
#endif
550-
#endif
551531
}
552532
}
553533
}
@@ -573,28 +553,43 @@ PropertyVector& VideoProperties::fillVector(PropertyVector& data) const
573553
addProperty(data, "colorRange", &VideoProperties::getColorRange);
574554
addProperty(data, "colorPrimaries", &VideoProperties::getColorPrimaries);
575555
addProperty(data, "chromaSampleLocation", &VideoProperties::getChromaSampleLocation);
576-
addProperty(data, "interlaced ", &VideoProperties::isInterlaced);
577-
addProperty(data, "topFieldFirst", &VideoProperties::isTopFieldFirst);
578556
addProperty(data, "fieldOrder", &VideoProperties::getFieldOrder);
579557
addProperty(data, "fps", &VideoProperties::getFps);
580558
addProperty(data, "nbFrame", &VideoProperties::getNbFrames);
581559
addProperty(data, "ticksPerFrame", &VideoProperties::getTicksPerFrame);
582560
addProperty(data, "bitRate", &VideoProperties::getBitRate);
583561
addProperty(data, "maxBitRate", &VideoProperties::getMaxBitRate);
584562
addProperty(data, "minBitRate", &VideoProperties::getMinBitRate);
585-
addProperty(data, "gopSize", &VideoProperties::getGopSize);
563+
addProperty(data, "hasBFrames", &VideoProperties::hasBFrames);
564+
addProperty(data, "referencesFrames", &VideoProperties::getReferencesFrames);
586565

587-
std::string gop;
588-
for(size_t frameIndex = 0; frameIndex < _gopStructure.size(); ++frameIndex)
566+
// Add properties available when decode first gop
567+
if(_levelAnalysis < eAnalyseLevelFirstGop)
589568
{
590-
gop += _gopStructure.at(frameIndex).first;
591-
gop += " ";
569+
detail::add(data, "gopSize", detail::propertyValueIfError);
570+
detail::add(data, "gop", detail::propertyValueIfError);
571+
detail::add(data, "interlaced", detail::propertyValueIfError);
572+
detail::add(data, "topFieldFirst", detail::propertyValueIfError);
592573
}
593-
detail::add(data, "gop", gop);
594-
// detail::add( data, "isClosedGop", isClosedGop() );
574+
else
575+
{
576+
addProperty(data, "gopSize", &VideoProperties::getGopSize);
595577

596-
addProperty(data, "hasBFrames", &VideoProperties::hasBFrames);
597-
addProperty(data, "referencesFrames", &VideoProperties::getReferencesFrames);
578+
std::stringstream gop;
579+
for(size_t frameIndex = 0; frameIndex < _gopStructure.size(); ++frameIndex)
580+
{
581+
gop << _gopStructure.at(frameIndex).first;
582+
gop << "(";
583+
gop << _gopStructure.at(frameIndex).second;;
584+
gop << ")";
585+
gop << " ";
586+
}
587+
detail::add(data, "gop", gop.str());
588+
// detail::add( data, "isClosedGop", isClosedGop() );
589+
590+
addProperty(data, "interlaced ", &VideoProperties::isInterlaced);
591+
addProperty(data, "topFieldFirst", &VideoProperties::isTopFieldFirst);
592+
}
598593

599594
// Add properties of the pixel
600595
PropertyVector pixelProperties;

0 commit comments

Comments
 (0)