* 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:
@@ -105,6 +105,10 @@ AVCodecDecoder::AVCodecDecoder()
|
|||||||
fOutputBufferSize(0)
|
fOutputBufferSize(0)
|
||||||
{
|
{
|
||||||
TRACE("AVCodecDecoder::AVCodecDecoder()\n");
|
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;
|
status_t ret = B_OK;
|
||||||
// Reset the FFmpeg codec to flush buffers, so we keep the sync
|
// 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)
|
if (fCodecInitDone)
|
||||||
avcodec_flush_buffers(fContext);
|
avcodec_flush_buffers(fContext);
|
||||||
#endif
|
|
||||||
|
|
||||||
// Flush internal buffers as well.
|
// Flush internal buffers as well.
|
||||||
fChunkBuffer = NULL;
|
fChunkBuffer = NULL;
|
||||||
@@ -305,8 +299,6 @@ AVCodecDecoder::Decode(void* outBuffer, int64* outFrameCount,
|
|||||||
else
|
else
|
||||||
ret = _DecodeVideo(outBuffer, outFrameCount, mediaHeader, info);
|
ret = _DecodeVideo(outBuffer, outFrameCount, mediaHeader, info);
|
||||||
|
|
||||||
fStartTime = (bigtime_t)(1000000LL * fFrame / fOutputFrameRate);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,7 +392,7 @@ AVCodecDecoder::_NegotiateAudioOutputFormat(media_format* inOutFormat)
|
|||||||
fOutputBufferOffset = 0;
|
fOutputBufferOffset = 0;
|
||||||
fOutputBufferSize = 0;
|
fOutputBufferSize = 0;
|
||||||
|
|
||||||
av_init_packet(&fAudioTempPacket);
|
av_init_packet(&fTempPacket);
|
||||||
|
|
||||||
inOutFormat->require_flags = 0;
|
inOutFormat->require_flags = 0;
|
||||||
inOutFormat->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
|
inOutFormat->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
|
||||||
@@ -586,18 +578,16 @@ AVCodecDecoder::_DecodeAudio(void* _buffer, int64* outFrameCount,
|
|||||||
}
|
}
|
||||||
fChunkBufferOffset = 0;
|
fChunkBufferOffset = 0;
|
||||||
fStartTime = chunkMediaHeader.start_time;
|
fStartTime = chunkMediaHeader.start_time;
|
||||||
if (*outFrameCount == 0)
|
|
||||||
mediaHeader->start_time = chunkMediaHeader.start_time;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fAudioTempPacket.data = (uint8_t*)fChunkBuffer + fChunkBufferOffset;
|
fTempPacket.data = (uint8_t*)fChunkBuffer + fChunkBufferOffset;
|
||||||
fAudioTempPacket.size = fChunkBufferSize;
|
fTempPacket.size = fChunkBufferSize;
|
||||||
// Initialize decodedBytes to the output buffer size.
|
// Initialize decodedBytes to the output buffer size.
|
||||||
int decodedBytes = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
int decodedBytes = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
||||||
int usedBytes = avcodec_decode_audio3(fContext,
|
int usedBytes = avcodec_decode_audio3(fContext,
|
||||||
(int16*)fOutputBuffer, &decodedBytes, &fAudioTempPacket);
|
(int16*)fOutputBuffer, &decodedBytes, &fTempPacket);
|
||||||
if (usedBytes < 0 && !fAudioDecodeError) {
|
if (usedBytes < 0 && !fAudioDecodeError) {
|
||||||
// Failure
|
// Report failure if not done already
|
||||||
printf("########### audio decode error, "
|
printf("########### audio decode error, "
|
||||||
"fChunkBufferSize %ld, fChunkBufferOffset %ld\n",
|
"fChunkBufferSize %ld, fChunkBufferOffset %ld\n",
|
||||||
fChunkBufferSize, fChunkBufferOffset);
|
fChunkBufferSize, fChunkBufferOffset);
|
||||||
@@ -608,12 +598,14 @@ AVCodecDecoder::_DecodeAudio(void* _buffer, int64* outFrameCount,
|
|||||||
// Skip the chunk buffer data entirely.
|
// Skip the chunk buffer data entirely.
|
||||||
usedBytes = fChunkBufferSize;
|
usedBytes = fChunkBufferSize;
|
||||||
decodedBytes = 0;
|
decodedBytes = 0;
|
||||||
|
// Assume the audio decoded until now is broken.
|
||||||
|
memset(_buffer, 0, buffer - (uint8*)_buffer);
|
||||||
} else {
|
} else {
|
||||||
// Success
|
// Success
|
||||||
fAudioDecodeError = false;
|
fAudioDecodeError = false;
|
||||||
}
|
}
|
||||||
//printf(" chunk size: %d, decoded: %d, used: %d\n",
|
//printf(" chunk size: %d, decoded: %d, used: %d\n",
|
||||||
//fAudioTempPacket.size, decodedBytes, usedBytes);
|
//fTempPacket.size, decodedBytes, usedBytes);
|
||||||
|
|
||||||
fChunkBufferOffset += usedBytes;
|
fChunkBufferOffset += usedBytes;
|
||||||
fChunkBufferSize -= usedBytes;
|
fChunkBufferSize -= usedBytes;
|
||||||
@@ -622,6 +614,7 @@ AVCodecDecoder::_DecodeAudio(void* _buffer, int64* outFrameCount,
|
|||||||
}
|
}
|
||||||
fFrame += *outFrameCount;
|
fFrame += *outFrameCount;
|
||||||
TRACE_AUDIO(" frame count: %lld current: %lld\n", *outFrameCount, fFrame);
|
TRACE_AUDIO(" frame count: %lld current: %lld\n", *outFrameCount, fFrame);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -654,7 +647,8 @@ AVCodecDecoder::_DecodeVideo(void* outBuffer, int64* outFrameCount,
|
|||||||
firstRun = false;
|
firstRun = false;
|
||||||
|
|
||||||
mediaHeader->type = B_MEDIA_RAW_VIDEO;
|
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->file_pos = 0;
|
||||||
mediaHeader->orig_size = 0;
|
mediaHeader->orig_size = 0;
|
||||||
mediaHeader->u.raw_video.field_gamma = 1.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
|
// packet buffers are supposed to contain complete frames only so we
|
||||||
// don't seem to be required to buffer any packets because not the
|
// don't seem to be required to buffer any packets because not the
|
||||||
// complete packet has been read.
|
// complete packet has been read.
|
||||||
|
fTempPacket.data = (uint8_t*)data;
|
||||||
|
fTempPacket.size = size;
|
||||||
int gotPicture = 0;
|
int gotPicture = 0;
|
||||||
int len = avcodec_decode_video(fContext, fInputPicture, &gotPicture,
|
int len = avcodec_decode_video2(fContext, fInputPicture, &gotPicture,
|
||||||
(uint8_t*)data, size);
|
&fTempPacket);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
TRACE("[v] AVCodecDecoder: error in decoding frame %lld: %d\n",
|
TRACE("[v] AVCodecDecoder: error in decoding frame %lld: %d\n",
|
||||||
fFrame, len);
|
fFrame, len);
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ private:
|
|||||||
int32 fOutputBufferOffset;
|
int32 fOutputBufferOffset;
|
||||||
int32 fOutputBufferSize;
|
int32 fOutputBufferSize;
|
||||||
|
|
||||||
AVPacket fAudioTempPacket;
|
AVPacket fTempPacket;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AVCODEC_DECODER_H
|
#endif // AVCODEC_DECODER_H
|
||||||
|
|||||||
Reference in New Issue
Block a user