Skip to content

Commit 702a618

Browse files
jdsgomesBruno Korbardatumbox
authored andcommitted
[fbsync] Attempt to fix FFMPEG 5.0 compatibility (#5644)
Summary: * fix for FFMPEG 5.0 * Attempt to fix memory leak * early stop when mem alloc fails * fix c lint error * fix bug * revert changes * remove incorrect av_packet_free * add `av_packet_free` to subtitle stream * Addressing subtitle stream comments * addressing decoder changes * nit * addressing datumbox concernsz * averror push * addressing comments * Apply suggestions from code review * add new error code to documentation * re-introducing timeout * fix c++ syntax (Note: this ignores all push blocking failures!) Reviewed By: datumbox Differential Revision: D35216769 fbshipit-source-id: e3489471406663c8e71fc239164a682993771db3 Co-authored-by: Bruno Korbar <[email protected]> Co-authored-by: Vasilis Vryniotis <[email protected]> Co-authored-by: Joao Gomes <[email protected]> Co-authored-by: Joao Gomes <[email protected]>
1 parent 0b097a3 commit 702a618

File tree

3 files changed

+49
-48
lines changed

3 files changed

+49
-48
lines changed

torchvision/csrc/io/decoder/decoder.cpp

Lines changed: 26 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,6 @@ constexpr size_t kIoBufferSize = 96 * 1024;
1818
constexpr size_t kIoPaddingSize = AV_INPUT_BUFFER_PADDING_SIZE;
1919
constexpr size_t kLogBufferSize = 1024;
2020

21-
int ffmpeg_lock(void** mutex, enum AVLockOp op) {
22-
std::mutex** handle = (std::mutex**)mutex;
23-
switch (op) {
24-
case AV_LOCK_CREATE:
25-
*handle = new std::mutex();
26-
break;
27-
case AV_LOCK_OBTAIN:
28-
(*handle)->lock();
29-
break;
30-
case AV_LOCK_RELEASE:
31-
(*handle)->unlock();
32-
break;
33-
case AV_LOCK_DESTROY:
34-
delete *handle;
35-
break;
36-
}
37-
return 0;
38-
}
39-
4021
bool mapFfmpegType(AVMediaType media, MediaType* type) {
4122
switch (media) {
4223
case AVMEDIA_TYPE_AUDIO:
@@ -202,8 +183,6 @@ void Decoder::initOnce() {
202183
avcodec_register_all();
203184
#endif
204185
avformat_network_init();
205-
// register ffmpeg lock manager
206-
av_lockmgr_register(&ffmpeg_lock);
207186
av_log_set_callback(Decoder::logFunction);
208187
av_log_set_level(AV_LOG_ERROR);
209188
VLOG(1) << "Registered ffmpeg libs";
@@ -277,7 +256,7 @@ bool Decoder::init(
277256
break;
278257
}
279258

280-
fmt = av_find_input_format(fmtName);
259+
fmt = (AVInputFormat*)av_find_input_format(fmtName);
281260
}
282261

283262
const size_t avioCtxBufferSize = kIoBufferSize;
@@ -495,8 +474,8 @@ void Decoder::cleanUp() {
495474

496475
// function does actual work, derived class calls it in working thread
497476
// periodically. On success method returns 0, ENODATA on EOF, ETIMEDOUT if
498-
// no frames got decoded in the specified timeout time, and error on
499-
// unrecoverable error.
477+
// no frames got decoded in the specified timeout time, AVERROR_BUFFER_TOO_SMALL
478+
// when unable to allocate packet and error on unrecoverable error
500479
int Decoder::getFrame(size_t workingTimeInMs) {
501480
if (inRange_.none()) {
502481
return ENODATA;
@@ -505,10 +484,15 @@ int Decoder::getFrame(size_t workingTimeInMs) {
505484
// once decode() method gets called and grab some bytes
506485
// run this method again
507486
// init package
508-
AVPacket avPacket;
509-
av_init_packet(&avPacket);
510-
avPacket.data = nullptr;
511-
avPacket.size = 0;
487+
// update 03/22: moving memory management to ffmpeg
488+
AVPacket* avPacket;
489+
avPacket = av_packet_alloc();
490+
if (avPacket == nullptr) {
491+
LOG(ERROR) << "decoder as not able to allocate the packet.";
492+
return AVERROR_BUFFER_TOO_SMALL;
493+
}
494+
avPacket->data = nullptr;
495+
avPacket->size = 0;
512496

513497
auto end = std::chrono::steady_clock::now() +
514498
std::chrono::milliseconds(workingTimeInMs);
@@ -520,8 +504,12 @@ int Decoder::getFrame(size_t workingTimeInMs) {
520504
int result = 0;
521505
size_t decodingErrors = 0;
522506
bool decodedFrame = false;
523-
while (!interrupted_ && inRange_.any() && !decodedFrame && watcher()) {
524-
result = av_read_frame(inputCtx_, &avPacket);
507+
while (!interrupted_ && inRange_.any() && !decodedFrame) {
508+
if (watcher() == false) {
509+
result = ETIMEDOUT;
510+
break;
511+
}
512+
result = av_read_frame(inputCtx_, avPacket);
525513
if (result == AVERROR(EAGAIN)) {
526514
VLOG(4) << "Decoder is busy...";
527515
std::this_thread::yield();
@@ -538,10 +526,11 @@ int Decoder::getFrame(size_t workingTimeInMs) {
538526
break;
539527
}
540528

541-
// get stream
542-
auto stream = findByIndex(avPacket.stream_index);
529+
// get stream; if stream cannot be found reset the packet to
530+
// default settings
531+
auto stream = findByIndex(avPacket->stream_index);
543532
if (stream == nullptr || !inRange_.test(stream->getIndex())) {
544-
av_packet_unref(&avPacket);
533+
av_packet_unref(avPacket);
545534
continue;
546535
}
547536

@@ -553,7 +542,7 @@ int Decoder::getFrame(size_t workingTimeInMs) {
553542
bool hasMsg = false;
554543
// packet either got consumed completely or not at all
555544
if ((result = processPacket(
556-
stream, &avPacket, &gotFrame, &hasMsg, params_.fastSeek)) < 0) {
545+
stream, avPacket, &gotFrame, &hasMsg, params_.fastSeek)) < 0) {
557546
LOG(ERROR) << "processPacket failed with code: " << result;
558547
break;
559548
}
@@ -585,20 +574,18 @@ int Decoder::getFrame(size_t workingTimeInMs) {
585574

586575
result = 0;
587576

588-
av_packet_unref(&avPacket);
577+
av_packet_unref(avPacket);
589578
}
590579

591-
av_packet_unref(&avPacket);
592-
580+
av_packet_free(&avPacket);
593581
VLOG(2) << "Interrupted loop"
594582
<< ", interrupted_ " << interrupted_ << ", inRange_.any() "
595583
<< inRange_.any() << ", decodedFrame " << decodedFrame << ", result "
596584
<< result;
597585

598586
// loop can be terminated, either by:
599587
// 1. explcitly iterrupted
600-
// 2. terminated by workable timeout
601-
// 3. unrecoverable error or ENODATA (end of stream)
588+
// 3. unrecoverable error or ENODATA (end of stream) or ETIMEDOUT (timeout)
602589
// 4. decoded frames pts are out of the specified range
603590
// 5. success decoded frame
604591
if (interrupted_) {

torchvision/csrc/io/decoder/stream.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Stream::~Stream() {
2828

2929
// look up the proper CODEC querying the function
3030
AVCodec* Stream::findCodec(AVCodecParameters* params) {
31-
return avcodec_find_decoder(params->codec_id);
31+
return (AVCodec*)avcodec_find_decoder(params->codec_id);
3232
}
3333

3434
// Allocate memory for the AVCodecContext, which will hold the context for

torchvision/csrc/io/decoder/subtitle_stream.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,34 @@ int SubtitleStream::initFormat() {
4343
int SubtitleStream::analyzePacket(const AVPacket* packet, bool* gotFrame) {
4444
// clean-up
4545
releaseSubtitle();
46+
47+
// FIXME: should this even be created?
48+
AVPacket* avPacket;
49+
avPacket = av_packet_alloc();
50+
if (avPacket == nullptr) {
51+
LOG(ERROR)
52+
<< "decoder as not able to allocate the subtitle-specific packet.";
53+
// alternative to ENOMEM
54+
return AVERROR_BUFFER_TOO_SMALL;
55+
}
56+
avPacket->data = nullptr;
57+
avPacket->size = 0;
4658
// check flush packet
47-
AVPacket avPacket;
48-
av_init_packet(&avPacket);
49-
avPacket.data = nullptr;
50-
avPacket.size = 0;
51-
auto pkt = packet ? *packet : avPacket;
59+
auto pkt = packet ? packet : avPacket;
60+
5261
int gotFramePtr = 0;
53-
int result = avcodec_decode_subtitle2(codecCtx_, &sub_, &gotFramePtr, &pkt);
62+
// is these a better way than cast from const?
63+
int result =
64+
avcodec_decode_subtitle2(codecCtx_, &sub_, &gotFramePtr, (AVPacket*)pkt);
5465

5566
if (result < 0) {
5667
LOG(ERROR) << "avcodec_decode_subtitle2 failed, err: "
5768
<< Util::generateErrorDesc(result);
69+
// free the packet we've created
70+
av_packet_free(&avPacket);
5871
return result;
5972
} else if (result == 0) {
60-
result = pkt.size; // discard the rest of the package
73+
result = pkt->size; // discard the rest of the package
6174
}
6275

6376
sub_.release = gotFramePtr;
@@ -66,9 +79,10 @@ int SubtitleStream::analyzePacket(const AVPacket* packet, bool* gotFrame) {
6679
// set proper pts in us
6780
if (gotFramePtr) {
6881
sub_.pts = av_rescale_q(
69-
pkt.pts, inputCtx_->streams[format_.stream]->time_base, timeBaseQ);
82+
pkt->pts, inputCtx_->streams[format_.stream]->time_base, timeBaseQ);
7083
}
7184

85+
av_packet_free(&avPacket);
7286
return result;
7387
}
7488

0 commit comments

Comments
 (0)