* Simplified "extra data" handling/allocation code a bit.
* Added debugging facility to dump the first 100 packets of a video stream to a debug file on the Desktop. * When needing to flush packets, avcodec_flush_buffers() is unfortunately not reliable. For audio codecs, the work around was to close and reopen the codec in Seek(). Do this also for video codecs. Makes H.264 more reliable here. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31503 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -28,6 +28,14 @@
|
|||||||
# define TRACE(x...)
|
# define TRACE(x...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//#define LOG_STREAM_TO_FILE
|
||||||
|
#ifdef LOG_STREAM_TO_FILE
|
||||||
|
# include <File.h>
|
||||||
|
static BFile sStreamLogFile("/boot/home/Desktop/AVCodecDebugStream.raw",
|
||||||
|
B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
|
||||||
|
static int sDumpedPackets = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct wave_format_ex {
|
struct wave_format_ex {
|
||||||
uint16 format_tag;
|
uint16 format_tag;
|
||||||
@@ -103,8 +111,8 @@ AVCodecDecoder::~AVCodecDecoder()
|
|||||||
free(fInputPicture);
|
free(fInputPicture);
|
||||||
free(fContext);
|
free(fContext);
|
||||||
|
|
||||||
delete [] fExtraData;
|
delete[] fExtraData;
|
||||||
delete [] fOutputBuffer;
|
delete[] fOutputBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -182,38 +190,40 @@ AVCodecDecoder::Setup(media_format* ioEncodedFormat, const void* infoBuffer,
|
|||||||
if (gCodecTable[i].family == descr.family
|
if (gCodecTable[i].family == descr.family
|
||||||
&& gCodecTable[i].fourcc == cid) {
|
&& gCodecTable[i].fourcc == cid) {
|
||||||
fCodec = avcodec_find_decoder(gCodecTable[i].id);
|
fCodec = avcodec_find_decoder(gCodecTable[i].id);
|
||||||
if (!fCodec) {
|
if (fCodec == NULL) {
|
||||||
TRACE("AVCodecDecoder: unable to find the correct ffmpeg "
|
TRACE("AVCodecDecoder: unable to find the correct FFmpeg "
|
||||||
"decoder (id = %d)!!!\n",gCodecTable[i].id);
|
"decoder (id = %d)\n", gCodecTable[i].id);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
TRACE("AVCodecDecoder: found decoder %s\n",fCodec->name);
|
TRACE("AVCodecDecoder: found decoder %s\n",fCodec->name);
|
||||||
|
|
||||||
|
const void* extraData = infoBuffer;
|
||||||
|
fExtraDataSize = infoSize;
|
||||||
if (gCodecTable[i].family == B_WAV_FORMAT_FAMILY
|
if (gCodecTable[i].family == B_WAV_FORMAT_FAMILY
|
||||||
&& infoSize >= sizeof(wave_format_ex)) {
|
&& infoSize >= sizeof(wave_format_ex)) {
|
||||||
const wave_format_ex *wfmt_data
|
// Special case extra data in B_WAV_FORMAT_FAMILY
|
||||||
= (const wave_format_ex *)infoBuffer;
|
const wave_format_ex* waveFormatData
|
||||||
size_t wfmt_size = infoSize;
|
= (const wave_format_ex*)infoBuffer;
|
||||||
if (wfmt_data && wfmt_size) {
|
|
||||||
fBlockAlign = wfmt_data->block_align;
|
size_t waveFormatSize = infoSize;
|
||||||
fExtraDataSize = wfmt_data->extra_size;
|
if (waveFormatData != NULL && waveFormatSize > 0) {
|
||||||
if (fExtraDataSize) {
|
fBlockAlign = waveFormatData->block_align;
|
||||||
fExtraData = new char [fExtraDataSize];
|
fExtraDataSize = waveFormatData->extra_size;
|
||||||
memcpy(fExtraData, wfmt_data + 1, fExtraDataSize);
|
// skip the wave_format_ex from the extra data.
|
||||||
}
|
extraData = waveFormatData + 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fBlockAlign
|
fBlockAlign
|
||||||
= ioEncodedFormat->u.encoded_audio.output.buffer_size;
|
= ioEncodedFormat->u.encoded_audio.output.buffer_size;
|
||||||
|
}
|
||||||
|
printf("XXX extra data size %ld\n", infoSize);
|
||||||
|
if (extraData != NULL && fExtraDataSize > 0) {
|
||||||
TRACE("AVCodecDecoder: extra data size %ld\n", infoSize);
|
TRACE("AVCodecDecoder: extra data size %ld\n", infoSize);
|
||||||
fExtraDataSize = infoSize;
|
fExtraData = new(std::nothrow) char[fExtraDataSize];
|
||||||
if (fExtraDataSize) {
|
if (fExtraData != NULL)
|
||||||
fExtraData = new(std::nothrow) char[fExtraDataSize];
|
memcpy(fExtraData, infoBuffer, fExtraDataSize);
|
||||||
if (fExtraData != NULL)
|
else
|
||||||
memcpy(fExtraData, infoBuffer, fExtraDataSize);
|
fExtraDataSize = 0;
|
||||||
else
|
|
||||||
fExtraDataSize = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fInputFormat = *ioEncodedFormat;
|
fInputFormat = *ioEncodedFormat;
|
||||||
@@ -231,13 +241,18 @@ AVCodecDecoder::Seek(uint32 seekTo, int64 seekFrame, int64* frame,
|
|||||||
bigtime_t seekTime, bigtime_t* time)
|
bigtime_t seekTime, bigtime_t* time)
|
||||||
{
|
{
|
||||||
// Reset the FFmpeg codec to flush buffers, so we keep the sync
|
// Reset the FFmpeg codec to flush buffers, so we keep the sync
|
||||||
// TODO: Maybe that should be done for video codecs, too?
|
#if 1
|
||||||
if (fIsAudio && fCodecInitDone) {
|
if (fCodecInitDone) {
|
||||||
fCodecInitDone = false;
|
fCodecInitDone = false;
|
||||||
avcodec_close(fContext);
|
avcodec_close(fContext);
|
||||||
fCodecInitDone = (avcodec_open(fContext, fCodec) >= 0);
|
fCodecInitDone = (avcodec_open(fContext, fCodec) >= 0);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
// For example, this doesn't work on the H.264 codec. :-/
|
||||||
|
if (fCodecInitDone)
|
||||||
|
avcodec_flush_buffers(fContext);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (seekTo == B_MEDIA_SEEK_TO_TIME) {
|
if (seekTo == B_MEDIA_SEEK_TO_TIME) {
|
||||||
TRACE("AVCodecDecoder::Seek by time ");
|
TRACE("AVCodecDecoder::Seek by time ");
|
||||||
TRACE("from frame %Ld and time %.6f TO Required Time %.6f. ",
|
TRACE("from frame %Ld and time %.6f TO Required Time %.6f. ",
|
||||||
@@ -388,11 +403,11 @@ AVCodecDecoder::_NegotiateVideoOutputFormat(media_format* inOutFormat)
|
|||||||
|
|
||||||
fOutputFrameRate = fOutputVideoFormat.field_rate;
|
fOutputFrameRate = fOutputVideoFormat.field_rate;
|
||||||
|
|
||||||
fContext->extradata = (uint8_t *)fExtraData;
|
fContext->extradata = (uint8_t*)fExtraData;
|
||||||
fContext->extradata_size = fExtraDataSize;
|
fContext->extradata_size = fExtraDataSize;
|
||||||
|
|
||||||
// if (fInputFormat.MetaDataSize() > 0) {
|
// if (fInputFormat.MetaDataSize() > 0) {
|
||||||
// fContext->extradata = (uint8_t *)fInputFormat.MetaData();
|
// fContext->extradata = (uint8_t*)fInputFormat.MetaData();
|
||||||
// fContext->extradata_size = fInputFormat.MetaDataSize();
|
// fContext->extradata_size = fInputFormat.MetaDataSize();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@@ -564,6 +579,15 @@ AVCodecDecoder::_DecodeVideo(void* outBuffer, int64* outFrameCount,
|
|||||||
"GetNextChunk(): %s\n", strerror(err));
|
"GetNextChunk(): %s\n", strerror(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
#ifdef LOG_STREAM_TO_FILE
|
||||||
|
if (sDumpedPackets < 100) {
|
||||||
|
sStreamLogFile.Write(data, size);
|
||||||
|
printf("wrote %ld bytes\n", size);
|
||||||
|
sDumpedPackets++;
|
||||||
|
} else if (sDumpedPackets == 100)
|
||||||
|
sStreamLogFile.Unset();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (firstRun) {
|
if (firstRun) {
|
||||||
firstRun = false;
|
firstRun = false;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user