Author: stippi Date: 2010-09-24 18:40:56 +0200 (Fri, 24 Sep 2010) New Revision: 38806 Changeset: http://dev.haiku-os.org/changeset/38806 Modified: haiku/trunk/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp haiku/trunk/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h Log: * Renamed fAudioTempPacket to fTempPacket and use it for calling the new video decoding function. This just avoids a warning generated from the libavcodec sources. The function used before did the exact same thing... * Maintain fStartTime correctly in _DecodeVideo(). Don't overwrite it with a calculated starttime in Decode(). This will allow drift to bubble up to the higher layers. * Do not use the previously required hack to close and reopen the AVCodec after seeking. avcodec_flush_buffers() seems to work fine now, and for certain stream types (MPEG1, MPEG2 video for example) the keyframe is correctly used after seeking. Modified: haiku/trunk/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp =================================================================== --- haiku/trunk/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp 2010-09-24 16:35:11 UTC (rev 38805) +++ haiku/trunk/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp 2010-09-24 16:40:56 UTC (rev 38806) @@ -105,6 +105,10 @@ fOutputBufferSize(0) { TRACE("AVCodecDecoder::AVCodecDecoder()\n"); + + fContext->error_recognition = FF_ER_CAREFUL; + fContext->error_concealment = 3; + avcodec_thread_init(fContext, 1); } @@ -241,18 +245,8 @@ { status_t ret = B_OK; // Reset the FFmpeg codec to flush buffers, so we keep the sync -#if 1 - if (fCodecInitDone) { - avcodec_close(fContext); - fCodecInitDone = avcodec_open(fContext, fCodec) >= 0; - if (!fCodecInitDone) - ret = B_ERROR; - } -#else - // For example, this doesn't work on the H.264 codec. :-/ if (fCodecInitDone) avcodec_flush_buffers(fContext); -#endif // Flush internal buffers as well. fChunkBuffer = NULL; @@ -305,8 +299,6 @@ else ret = _DecodeVideo(outBuffer, outFrameCount, mediaHeader, info); - fStartTime = (bigtime_t)(1000000LL * fFrame / fOutputFrameRate); - return ret; } @@ -400,7 +392,7 @@ fOutputBufferOffset = 0; fOutputBufferSize = 0; - av_init_packet(&fAudioTempPacket); + av_init_packet(&fTempPacket); inOutFormat->require_flags = 0; inOutFormat->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS; @@ -586,18 +578,16 @@ } fChunkBufferOffset = 0; fStartTime = chunkMediaHeader.start_time; - if (*outFrameCount == 0) - mediaHeader->start_time = chunkMediaHeader.start_time; } - fAudioTempPacket.data = (uint8_t*)fChunkBuffer + fChunkBufferOffset; - fAudioTempPacket.size = fChunkBufferSize; + fTempPacket.data = (uint8_t*)fChunkBuffer + fChunkBufferOffset; + fTempPacket.size = fChunkBufferSize; // Initialize decodedBytes to the output buffer size. int decodedBytes = AVCODEC_MAX_AUDIO_FRAME_SIZE; int usedBytes = avcodec_decode_audio3(fContext, - (int16*)fOutputBuffer, &decodedBytes, &fAudioTempPacket); + (int16*)fOutputBuffer, &decodedBytes, &fTempPacket); if (usedBytes < 0 && !fAudioDecodeError) { - // Failure + // Report failure if not done already printf("########### audio decode error, " "fChunkBufferSize %ld, fChunkBufferOffset %ld\n", fChunkBufferSize, fChunkBufferOffset); @@ -608,12 +598,14 @@ // Skip the chunk buffer data entirely. usedBytes = fChunkBufferSize; decodedBytes = 0; + // Assume the audio decoded until now is broken. + memset(_buffer, 0, buffer - (uint8*)_buffer); } else { // Success fAudioDecodeError = false; } //printf(" chunk size: %d, decoded: %d, used: %d\n", -//fAudioTempPacket.size, decodedBytes, usedBytes); +//fTempPacket.size, decodedBytes, usedBytes); fChunkBufferOffset += usedBytes; fChunkBufferSize -= usedBytes; @@ -622,6 +614,7 @@ } fFrame += *outFrameCount; TRACE_AUDIO(" frame count: %lld current: %lld\n", *outFrameCount, fFrame); + return B_OK; } @@ -654,7 +647,8 @@ firstRun = false; mediaHeader->type = B_MEDIA_RAW_VIDEO; -// mediaHeader->start_time = chunkMediaHeader.start_time; + mediaHeader->start_time = chunkMediaHeader.start_time; + fStartTime = chunkMediaHeader.start_time; mediaHeader->file_pos = 0; mediaHeader->orig_size = 0; mediaHeader->u.raw_video.field_gamma = 1.0; @@ -681,9 +675,11 @@ // packet buffers are supposed to contain complete frames only so we // don't seem to be required to buffer any packets because not the // complete packet has been read. + fTempPacket.data = (uint8_t*)data; + fTempPacket.size = size; int gotPicture = 0; - int len = avcodec_decode_video(fContext, fInputPicture, &gotPicture, - (uint8_t*)data, size); + int len = avcodec_decode_video2(fContext, fInputPicture, &gotPicture, + &fTempPacket); if (len < 0) { TRACE("[v] AVCodecDecoder: error in decoding frame %lld: %d\n", fFrame, len); Modified: haiku/trunk/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h =================================================================== --- haiku/trunk/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h 2010-09-24 16:35:11 UTC (rev 38805) +++ haiku/trunk/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h 2010-09-24 16:40:56 UTC (rev 38806) @@ -102,7 +102,7 @@ int32 fOutputBufferOffset; int32 fOutputBufferSize; - AVPacket fAudioTempPacket; + AVPacket fTempPacket; }; #endif // AVCODEC_DECODER_H