* 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.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38806 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2010-09-24 16:40:56 +00:00
parent a92abad742
commit 954d70d8c0
2 changed files with 20 additions and 24 deletions
@@ -105,6 +105,10 @@ AVCodecDecoder::AVCodecDecoder()
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 @@ AVCodecDecoder::SeekedTo(int64 frame, bigtime_t time)
{
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 @@ AVCodecDecoder::Decode(void* outBuffer, int64* outFrameCount,
else
ret = _DecodeVideo(outBuffer, outFrameCount, mediaHeader, info);
fStartTime = (bigtime_t)(1000000LL * fFrame / fOutputFrameRate);
return ret;
}
@@ -400,7 +392,7 @@ AVCodecDecoder::_NegotiateAudioOutputFormat(media_format* inOutFormat)
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 @@ AVCodecDecoder::_DecodeAudio(void* _buffer, int64* outFrameCount,
}
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 @@ AVCodecDecoder::_DecodeAudio(void* _buffer, int64* outFrameCount,
// 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 @@ AVCodecDecoder::_DecodeAudio(void* _buffer, int64* outFrameCount,
}
fFrame += *outFrameCount;
TRACE_AUDIO(" frame count: %lld current: %lld\n", *outFrameCount, fFrame);
return B_OK;
}
@@ -654,7 +647,8 @@ AVCodecDecoder::_DecodeVideo(void* outBuffer, int64* outFrameCount,
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 @@ AVCodecDecoder::_DecodeVideo(void* outBuffer, int64* outFrameCount,
// 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);
@@ -102,7 +102,7 @@ private:
int32 fOutputBufferOffset;
int32 fOutputBufferSize;
AVPacket fAudioTempPacket;
AVPacket fTempPacket;
};
#endif // AVCODEC_DECODER_H