From 4c8208af526192d38369539c97e7a795dde472ba Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Thu, 8 Nov 2018 19:39:57 +0100 Subject: [PATCH] ffmpeg: fix crash at end of video stream Mixing new and old style decoding APIs won't work. And we were still using the old API for managing the end of videos. Change-Id: Ic194ab98721455658ecefde4f951c3f1e43ae1be Reviewed-on: https://review.haiku-os.org/679 Reviewed-by: waddlesplash --- .../media/plugins/ffmpeg/AVCodecDecoder.cpp | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp index 23fb6af38c..85624bc995 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp @@ -1524,19 +1524,15 @@ AVCodecDecoder::_HandleNewVideoFrameAndUpdateSystemState() status_t AVCodecDecoder::_FlushOneVideoFrameFromDecoderBuffer() { - // Create empty fTempPacket to tell the video decoder it is time to flush - fTempPacket.data = NULL; - fTempPacket.size = 0; + // Tell the decoder there is nothing to send anymore + avcodec_send_packet(fCodecContext, NULL); - int gotVideoFrame = 0; - avcodec_decode_video2(fCodecContext, fRawDecodedPicture, &gotVideoFrame, - &fTempPacket); - // We are only interested in complete frames now, so ignore the return - // value. + // Get any remaining frame + int error = avcodec_receive_frame(fCodecContext, fRawDecodedPicture); - bool gotNoVideoFrame = gotVideoFrame == 0; - if (gotNoVideoFrame) { + if (error != 0 && error != AVERROR(EAGAIN)) { // video buffer is flushed successfully + // (or there is an error, not much we can do about it) return B_LAST_BUFFER_ERROR; } @@ -1565,10 +1561,15 @@ AVCodecDecoder::_FlushOneVideoFrameFromDecoderBuffer() void AVCodecDecoder::_UpdateMediaHeaderForVideoFrame() { + AVRational rationalTimestamp = av_make_q( + fRawDecodedPicture->pkt_dts, 1); + AVRational seconds = av_mul_q(rationalTimestamp, fCodecContext->time_base); + AVRational microseconds = av_mul_q(seconds, av_make_q(1000000, 1)); + fHeader.type = B_MEDIA_RAW_VIDEO; fHeader.file_pos = 0; fHeader.orig_size = 0; - fHeader.start_time = fRawDecodedPicture->pkt_dts; + fHeader.start_time = (bigtime_t)(av_q2d(microseconds)); fHeader.size_used = av_image_get_buffer_size( colorspace_to_pixfmt(fOutputColorSpace), fRawDecodedPicture->width, fRawDecodedPicture->height, 1);