* Coding style cleanup, some removal of dead code.
* Refactored NegotiateOutputFormat() and Decode() into two separate private methods each, one for video and one for audio. * Keep reading chunks when video decoding, until we have got a picture. This gets us scrambled video instead of a black picture for h264 in mpegts. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31457 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -12,12 +12,13 @@
|
|||||||
|
|
||||||
#include "AVCodecDecoder.h"
|
#include "AVCodecDecoder.h"
|
||||||
|
|
||||||
#include <Debug.h>
|
#include <new>
|
||||||
#include <OS.h>
|
|
||||||
#include <Bitmap.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define DO_PROFILING 0
|
#include <Bitmap.h>
|
||||||
|
#include <Debug.h>
|
||||||
|
|
||||||
|
|
||||||
#undef TRACE
|
#undef TRACE
|
||||||
//#define TRACE_AV_CODEC
|
//#define TRACE_AV_CODEC
|
||||||
@@ -27,6 +28,7 @@
|
|||||||
# define TRACE(x...)
|
# define TRACE(x...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct wave_format_ex {
|
struct wave_format_ex {
|
||||||
uint16 format_tag;
|
uint16 format_tag;
|
||||||
uint16 channels;
|
uint16 channels;
|
||||||
@@ -38,56 +40,68 @@ struct wave_format_ex {
|
|||||||
// extra_data[extra_size]
|
// extra_data[extra_size]
|
||||||
} _PACKED;
|
} _PACKED;
|
||||||
|
|
||||||
static bigtime_t diff1 = 0, diff2 = 0;
|
|
||||||
static long prof_cnt = 0;
|
|
||||||
|
|
||||||
// uncommenting will make Decode() set the current thread priority to time
|
// profiling related globals
|
||||||
// sharing, so it won't totally freeze if you busy-loop in there (to help debug
|
#define DO_PROFILING 0
|
||||||
// with CD Manager)
|
|
||||||
//#define UNREAL
|
static bigtime_t decodingTime = 0;
|
||||||
|
static bigtime_t conversionTime = 0;
|
||||||
|
static long profileCounter = 0;
|
||||||
|
|
||||||
|
|
||||||
AVCodecDecoder::AVCodecDecoder()
|
AVCodecDecoder::AVCodecDecoder()
|
||||||
: fHeader(),
|
:
|
||||||
|
fHeader(),
|
||||||
fInfo(),
|
fInfo(),
|
||||||
fInputFormat(),
|
fInputFormat(),
|
||||||
fOutputVideoFormat(),
|
fOutputVideoFormat(),
|
||||||
fFrame(0),
|
fFrame(0),
|
||||||
isAudio(false),
|
fIsAudio(false),
|
||||||
|
fCodecIndexInTable(-1),
|
||||||
fCodec(NULL),
|
fCodec(NULL),
|
||||||
ffc(NULL),
|
fContext(avcodec_alloc_context()),
|
||||||
|
fInputPicture(avcodec_alloc_frame()),
|
||||||
|
fOutputPicture(avcodec_alloc_frame()),
|
||||||
|
|
||||||
fCodecInitDone(false),
|
fCodecInitDone(false),
|
||||||
conv_func(NULL),
|
|
||||||
|
fFormatConversionFunc(NULL),
|
||||||
|
|
||||||
fExtraData(NULL),
|
fExtraData(NULL),
|
||||||
fExtraDataSize(0),
|
fExtraDataSize(0),
|
||||||
fBlockAlign(0),
|
fBlockAlign(0),
|
||||||
fOutputBuffer(0)
|
|
||||||
|
fStartTime(0),
|
||||||
|
fOutputFrameCount(0),
|
||||||
|
fOutputFrameRate(1.0),
|
||||||
|
fOutputFrameSize(0),
|
||||||
|
|
||||||
|
fOutputBuffer(NULL),
|
||||||
|
fOutputBufferOffset(0),
|
||||||
|
fOutputBufferSize(0)
|
||||||
{
|
{
|
||||||
TRACE("AVCodecDecoder::AVCodecDecoder()\n");
|
TRACE("AVCodecDecoder::AVCodecDecoder()\n");
|
||||||
|
|
||||||
ffc = avcodec_alloc_context();
|
|
||||||
ffpicture = avcodec_alloc_frame();
|
|
||||||
opicture = avcodec_alloc_frame();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AVCodecDecoder::~AVCodecDecoder()
|
AVCodecDecoder::~AVCodecDecoder()
|
||||||
{
|
{
|
||||||
TRACE("[%c] AVCodecDecoder::~AVCodecDecoder()\n", isAudio?('a'):('v'));
|
TRACE("[%c] AVCodecDecoder::~AVCodecDecoder()\n", fIsAudio?('a'):('v'));
|
||||||
|
|
||||||
#ifdef DO_PROFILING
|
#ifdef DO_PROFILING
|
||||||
if (prof_cnt > 0) {
|
if (profileCounter > 0) {
|
||||||
printf("[%c] profile: d1 = %lld, d2 = %lld (%Ld)\n",
|
printf("[%c] profile: d1 = %lld, d2 = %lld (%Ld)\n",
|
||||||
isAudio?('a'):('v'), diff1/prof_cnt, diff2/prof_cnt,
|
fIsAudio?('a'):('v'), decodingTime / profileCounter, conversionTime / profileCounter,
|
||||||
fFrame);
|
fFrame);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (fCodecInitDone)
|
if (fCodecInitDone)
|
||||||
avcodec_close(ffc);
|
avcodec_close(fContext);
|
||||||
|
|
||||||
free(opicture);
|
free(fOutputPicture);
|
||||||
free(ffpicture);
|
free(fInputPicture);
|
||||||
free(ffc);
|
free(fContext);
|
||||||
|
|
||||||
delete [] fExtraData;
|
delete [] fExtraData;
|
||||||
delete [] fOutputBuffer;
|
delete [] fOutputBuffer;
|
||||||
@@ -95,45 +109,47 @@ AVCodecDecoder::~AVCodecDecoder()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AVCodecDecoder::GetCodecInfo(media_codec_info *mci)
|
AVCodecDecoder::GetCodecInfo(media_codec_info* mci)
|
||||||
{
|
{
|
||||||
sprintf(mci->short_name, "ff:%s", fCodec->name);
|
sprintf(mci->short_name, "ff:%s", fCodec->name);
|
||||||
sprintf(mci->pretty_name, "%s (libavcodec %s)",
|
sprintf(mci->pretty_name, "%s (libavcodec %s)",
|
||||||
gCodecTable[ffcodec_index_in_table].prettyname, fCodec->name);
|
gCodecTable[fCodecIndexInTable].prettyname, fCodec->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
AVCodecDecoder::Setup(media_format *ioEncodedFormat, const void *infoBuffer,
|
AVCodecDecoder::Setup(media_format* ioEncodedFormat, const void* infoBuffer,
|
||||||
size_t infoSize)
|
size_t infoSize)
|
||||||
{
|
{
|
||||||
if (ioEncodedFormat->type != B_MEDIA_ENCODED_AUDIO
|
if (ioEncodedFormat->type != B_MEDIA_ENCODED_AUDIO
|
||||||
&& ioEncodedFormat->type != B_MEDIA_ENCODED_VIDEO)
|
&& ioEncodedFormat->type != B_MEDIA_ENCODED_VIDEO)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
isAudio = (ioEncodedFormat->type == B_MEDIA_ENCODED_AUDIO);
|
fIsAudio = (ioEncodedFormat->type == B_MEDIA_ENCODED_AUDIO);
|
||||||
TRACE("[%c] AVCodecDecoder::Setup()\n", isAudio?('a'):('v'));
|
TRACE("[%c] AVCodecDecoder::Setup()\n", fIsAudio?('a'):('v'));
|
||||||
|
|
||||||
if (isAudio && !fOutputBuffer)
|
if (fIsAudio && !fOutputBuffer)
|
||||||
fOutputBuffer = new char[AVCODEC_MAX_AUDIO_FRAME_SIZE];
|
fOutputBuffer = new char[AVCODEC_MAX_AUDIO_FRAME_SIZE];
|
||||||
|
|
||||||
//#if DEBUG
|
#ifdef TRACE_AV_CODEC
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
string_for_format(*ioEncodedFormat, buffer, sizeof(buffer));
|
string_for_format(*ioEncodedFormat, buffer, sizeof(buffer));
|
||||||
TRACE("[%c] input_format=%s\n", isAudio?('a'):('v'), buffer);
|
TRACE("[%c] input_format = %s\n", fIsAudio?('a'):('v'), buffer);
|
||||||
TRACE("[%c] infoSize=%ld\n", isAudio?('a'):('v'), infoSize);
|
TRACE("[%c] infoSize = %ld\n", fIsAudio?('a'):('v'), infoSize);
|
||||||
TRACE("[%c] user_data_type=%08lx\n", isAudio?('a'):('v'), ioEncodedFormat->user_data_type);
|
TRACE("[%c] user_data_type = %08lx\n", fIsAudio?('a'):('v'),
|
||||||
TRACE("[%c] meta_data_size=%ld\n", isAudio?('a'):('v'), ioEncodedFormat->MetaDataSize());
|
ioEncodedFormat->user_data_type);
|
||||||
TRACE("[%c] info_size=%ld\n", isAudio?('a'):('v'), infoSize);
|
TRACE("[%c] meta_data_size = %ld\n", fIsAudio?('a'):('v'),
|
||||||
//#endif
|
ioEncodedFormat->MetaDataSize());
|
||||||
|
TRACE("[%c] info_size = %ld\n", fIsAudio?('a'):('v'), infoSize);
|
||||||
|
#endif
|
||||||
|
|
||||||
media_format_description descr;
|
media_format_description descr;
|
||||||
for (int32 i = 0; gCodecTable[i].id; i++) {
|
for (int32 i = 0; gCodecTable[i].id; i++) {
|
||||||
ffcodec_index_in_table = i;
|
fCodecIndexInTable = i;
|
||||||
uint64 cid;
|
uint64 cid;
|
||||||
|
|
||||||
if (BMediaFormats().GetCodeFor(*ioEncodedFormat, gCodecTable[i].family,
|
if (BMediaFormats().GetCodeFor(*ioEncodedFormat,
|
||||||
&descr) == B_OK
|
gCodecTable[i].family, &descr) == B_OK
|
||||||
&& gCodecTable[i].type == ioEncodedFormat->type) {
|
&& gCodecTable[i].type == ioEncodedFormat->type) {
|
||||||
switch(gCodecTable[i].family) {
|
switch(gCodecTable[i].family) {
|
||||||
case B_WAV_FORMAT_FAMILY:
|
case B_WAV_FORMAT_FAMILY:
|
||||||
@@ -159,21 +175,22 @@ AVCodecDecoder::Setup(media_format *ioEncodedFormat, const void *infoBuffer,
|
|||||||
puts("ERR family");
|
puts("ERR family");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
TRACE(" 0x%04lx codec id = \"%c%c%c%c\"\n", uint32(cid), (char)((cid >> 24) & 0xff),
|
TRACE(" 0x%04lx codec id = \"%c%c%c%c\"\n", uint32(cid),
|
||||||
(char)((cid >> 16) & 0xff), (char)((cid >> 8) & 0xff),
|
(char)((cid >> 24) & 0xff), (char)((cid >> 16) & 0xff),
|
||||||
(char)(cid & 0xff));
|
(char)((cid >> 8) & 0xff), (char)(cid & 0xff));
|
||||||
|
|
||||||
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) {
|
||||||
TRACE("AVCodecDecoder: unable to find the correct ffmpeg decoder "
|
TRACE("AVCodecDecoder: unable to find the correct ffmpeg "
|
||||||
"(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);
|
||||||
|
|
||||||
if (gCodecTable[i].family == B_WAV_FORMAT_FAMILY && infoSize >= sizeof(wave_format_ex)) {
|
if (gCodecTable[i].family == B_WAV_FORMAT_FAMILY
|
||||||
|
&& infoSize >= sizeof(wave_format_ex)) {
|
||||||
const wave_format_ex *wfmt_data
|
const wave_format_ex *wfmt_data
|
||||||
= (const wave_format_ex *)infoBuffer;
|
= (const wave_format_ex *)infoBuffer;
|
||||||
size_t wfmt_size = infoSize;
|
size_t wfmt_size = infoSize;
|
||||||
@@ -186,12 +203,16 @@ AVCodecDecoder::Setup(media_format *ioEncodedFormat, const void *infoBuffer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fBlockAlign = ioEncodedFormat->u.encoded_audio.output.buffer_size;
|
fBlockAlign
|
||||||
TRACE("AVCodecDecoder: extra data size %ld\n",infoSize);
|
= ioEncodedFormat->u.encoded_audio.output.buffer_size;
|
||||||
|
TRACE("AVCodecDecoder: extra data size %ld\n", infoSize);
|
||||||
fExtraDataSize = infoSize;
|
fExtraDataSize = infoSize;
|
||||||
if (fExtraDataSize) {
|
if (fExtraDataSize) {
|
||||||
fExtraData = new char [fExtraDataSize];
|
fExtraData = new(std::nothrow) char[fExtraDataSize];
|
||||||
|
if (fExtraData != NULL)
|
||||||
memcpy(fExtraData, infoBuffer, fExtraDataSize);
|
memcpy(fExtraData, infoBuffer, fExtraDataSize);
|
||||||
|
else
|
||||||
|
fExtraDataSize = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,27 +227,28 @@ AVCodecDecoder::Setup(media_format *ioEncodedFormat, const void *infoBuffer,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
AVCodecDecoder::Seek(uint32 seekTo,
|
AVCodecDecoder::Seek(uint32 seekTo, int64 seekFrame, int64* frame,
|
||||||
int64 seekFrame, int64 *frame,
|
bigtime_t seekTime, bigtime_t* time)
|
||||||
bigtime_t seekTime, bigtime_t *time)
|
|
||||||
{
|
{
|
||||||
// reset the ffmpeg codec
|
// Reset the FFmpeg codec to flush buffers, so we keep the sync
|
||||||
// to flush buffers, so we keep the sync
|
// TODO: Maybe that should be done for video codecs, too?
|
||||||
if (isAudio && fCodecInitDone) {
|
if (fIsAudio && fCodecInitDone) {
|
||||||
fCodecInitDone = false;
|
fCodecInitDone = false;
|
||||||
avcodec_close(ffc);
|
avcodec_close(fContext);
|
||||||
fCodecInitDone = (avcodec_open(ffc, fCodec) >= 0);
|
fCodecInitDone = (avcodec_open(fContext, fCodec) >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
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. ", fFrame, fStartTime / 1000000.0, seekTime / 1000000.0);
|
TRACE("from frame %Ld and time %.6f TO Required Time %.6f. ",
|
||||||
|
fFrame, fStartTime / 1000000.0, seekTime / 1000000.0);
|
||||||
|
|
||||||
*frame = (int64)(seekTime * fOutputFrameRate / 1000000LL);
|
*frame = (int64)(seekTime * fOutputFrameRate / 1000000LL);
|
||||||
*time = seekTime;
|
*time = seekTime;
|
||||||
} else if (seekTo == B_MEDIA_SEEK_TO_FRAME) {
|
} else if (seekTo == B_MEDIA_SEEK_TO_FRAME) {
|
||||||
TRACE("AVCodecDecoder::Seek by Frame ");
|
TRACE("AVCodecDecoder::Seek by Frame ");
|
||||||
TRACE("from time %.6f and frame %Ld TO Required Frame %Ld. ", fStartTime / 1000000.0, fFrame, seekFrame);
|
TRACE("from time %.6f and frame %Ld TO Required Frame %Ld. ",
|
||||||
|
fStartTime / 1000000.0, fFrame, seekFrame);
|
||||||
|
|
||||||
*time = (bigtime_t)(seekFrame * 1000000LL / fOutputFrameRate);
|
*time = (bigtime_t)(seekFrame * 1000000LL / fOutputFrameRate);
|
||||||
*frame = seekFrame;
|
*frame = seekFrame;
|
||||||
@@ -241,19 +263,56 @@ AVCodecDecoder::Seek(uint32 seekTo,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
AVCodecDecoder::NegotiateOutputFormat(media_format *inout_format)
|
AVCodecDecoder::NegotiateOutputFormat(media_format* inOutFormat)
|
||||||
{
|
{
|
||||||
TRACE("[%c] AVCodecDecoder::NegotiateOutputFormat()\n", isAudio?('a'):('v'));
|
TRACE("AVCodecDecoder::NegotiateOutputFormat()\n",
|
||||||
|
fIsAudio?('a'):('v'));
|
||||||
|
|
||||||
int result;
|
#if TRACE_AV_CODEC
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
string_for_format(*inout_format, buffer, sizeof(buffer));
|
string_for_format(*inOutFormat, buffer, sizeof(buffer));
|
||||||
TRACE("[%c] in_format=%s\n", isAudio?('a'):('v'), buffer);
|
TRACE(" [%c] requested format = %s\n", fIsAudio?('a'):('v'), buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (isAudio) {
|
if (fIsAudio)
|
||||||
|
return _NegotiateAudioOutputFormat(inOutFormat);
|
||||||
|
else
|
||||||
|
return _NegotiateVideoOutputFormat(inOutFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AVCodecDecoder::Decode(void* outBuffer, int64* outFrameCount,
|
||||||
|
media_header* mediaHeader, media_decode_info* info)
|
||||||
|
{
|
||||||
|
if (!fCodecInitDone)
|
||||||
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
// TRACE("[%c] AVCodecDecoder::Decode() for time %Ld\n", fIsAudio?('a'):('v'),
|
||||||
|
// fStartTime);
|
||||||
|
|
||||||
|
mediaHeader->start_time = fStartTime;
|
||||||
|
|
||||||
|
status_t ret;
|
||||||
|
if (fIsAudio)
|
||||||
|
ret = _DecodeAudio(outBuffer, outFrameCount, mediaHeader, info);
|
||||||
|
else
|
||||||
|
ret = _DecodeVideo(outBuffer, outFrameCount, mediaHeader, info);
|
||||||
|
|
||||||
|
fStartTime = (bigtime_t)(1000000LL * fFrame / fOutputFrameRate);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AVCodecDecoder::_NegotiateAudioOutputFormat(media_format* inOutFormat)
|
||||||
|
{
|
||||||
|
TRACE("AVCodecDecoder::_NegotiateAudioOutputFormat()\n");
|
||||||
|
|
||||||
media_multi_audio_format outputAudioFormat;
|
media_multi_audio_format outputAudioFormat;
|
||||||
outputAudioFormat = media_raw_audio_format::wildcard;
|
outputAudioFormat = media_raw_audio_format::wildcard;
|
||||||
outputAudioFormat.format = media_raw_audio_format::B_AUDIO_SHORT;
|
outputAudioFormat.format = media_raw_audio_format::B_AUDIO_SHORT;
|
||||||
@@ -264,32 +323,34 @@ AVCodecDecoder::NegotiateOutputFormat(media_format *inout_format)
|
|||||||
= fInputFormat.u.encoded_audio.output.channel_count;
|
= fInputFormat.u.encoded_audio.output.channel_count;
|
||||||
outputAudioFormat.buffer_size
|
outputAudioFormat.buffer_size
|
||||||
= 1024 * fInputFormat.u.encoded_audio.output.channel_count;
|
= 1024 * fInputFormat.u.encoded_audio.output.channel_count;
|
||||||
inout_format->type = B_MEDIA_RAW_AUDIO;
|
inOutFormat->type = B_MEDIA_RAW_AUDIO;
|
||||||
inout_format->u.raw_audio = outputAudioFormat;
|
inOutFormat->u.raw_audio = outputAudioFormat;
|
||||||
|
|
||||||
ffc->bit_rate = (int) fInputFormat.u.encoded_audio.bit_rate;
|
fContext->bit_rate = (int)fInputFormat.u.encoded_audio.bit_rate;
|
||||||
ffc->sample_rate = (int) fInputFormat.u.encoded_audio.output.frame_rate;
|
fContext->sample_rate
|
||||||
ffc->channels = fInputFormat.u.encoded_audio.output.channel_count;
|
= (int)fInputFormat.u.encoded_audio.output.frame_rate;
|
||||||
ffc->block_align = fBlockAlign;
|
fContext->channels = fInputFormat.u.encoded_audio.output.channel_count;
|
||||||
ffc->extradata = (uint8_t *)fExtraData;
|
fContext->block_align = fBlockAlign;
|
||||||
ffc->extradata_size = fExtraDataSize;
|
fContext->extradata = (uint8_t*)fExtraData;
|
||||||
|
fContext->extradata_size = fExtraDataSize;
|
||||||
|
|
||||||
TRACE("bit_rate %d, sample_rate %d, channels %d, block_align %d, "
|
TRACE("bit_rate %d, sample_rate %d, channels %d, block_align %d, "
|
||||||
"extradata_size %d\n", ffc->bit_rate, ffc->sample_rate,
|
"extradata_size %d\n", fContext->bit_rate, fContext->sample_rate,
|
||||||
ffc->channels, ffc->block_align, ffc->extradata_size);
|
fContext->channels, fContext->block_align, fContext->extradata_size);
|
||||||
|
|
||||||
// close any previous instance
|
// close any previous instance
|
||||||
if (fCodecInitDone) {
|
if (fCodecInitDone) {
|
||||||
fCodecInitDone = false;
|
fCodecInitDone = false;
|
||||||
avcodec_close(ffc);
|
avcodec_close(fContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
// open new
|
// open new
|
||||||
result = avcodec_open(ffc, fCodec);
|
int result = avcodec_open(fContext, fCodec);
|
||||||
fCodecInitDone = (result >= 0);
|
fCodecInitDone = (result >= 0);
|
||||||
|
|
||||||
TRACE("audio: bit_rate = %d, sample_rate = %d, chans = %d Init = %d\n",
|
TRACE("audio: bit_rate = %d, sample_rate = %d, chans = %d Init = %d\n",
|
||||||
ffc->bit_rate, ffc->sample_rate, ffc->channels, result);
|
fContext->bit_rate, fContext->sample_rate, fContext->channels,
|
||||||
|
result);
|
||||||
|
|
||||||
fStartTime = 0;
|
fStartTime = 0;
|
||||||
fOutputFrameSize = 2 * outputAudioFormat.channel_count;
|
fOutputFrameSize = 2 * outputAudioFormat.channel_count;
|
||||||
@@ -301,8 +362,8 @@ AVCodecDecoder::NegotiateOutputFormat(media_format *inout_format)
|
|||||||
fOutputBufferOffset = 0;
|
fOutputBufferOffset = 0;
|
||||||
fOutputBufferSize = 0;
|
fOutputBufferSize = 0;
|
||||||
|
|
||||||
inout_format->require_flags = 0;
|
inOutFormat->require_flags = 0;
|
||||||
inout_format->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
|
inOutFormat->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
|
||||||
|
|
||||||
if (!fCodecInitDone) {
|
if (!fCodecInitDone) {
|
||||||
TRACE("avcodec_open() failed!\n");
|
TRACE("avcodec_open() failed!\n");
|
||||||
@@ -310,56 +371,63 @@ AVCodecDecoder::NegotiateOutputFormat(media_format *inout_format)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
} else { // VIDEO
|
|
||||||
|
status_t
|
||||||
|
AVCodecDecoder::_NegotiateVideoOutputFormat(media_format* inOutFormat)
|
||||||
|
{
|
||||||
|
TRACE("AVCodecDecoder::_NegotiateVideoOutputFormat()\n");
|
||||||
|
|
||||||
fOutputVideoFormat = fInputFormat.u.encoded_video.output;
|
fOutputVideoFormat = fInputFormat.u.encoded_video.output;
|
||||||
|
|
||||||
ffc->width = fOutputVideoFormat.display.line_width;
|
fContext->width = fOutputVideoFormat.display.line_width;
|
||||||
ffc->height = fOutputVideoFormat.display.line_count;
|
fContext->height = fOutputVideoFormat.display.line_count;
|
||||||
// ffc->frame_rate = (int)(fOutputVideoFormat.field_rate
|
// fContext->frame_rate = (int)(fOutputVideoFormat.field_rate
|
||||||
// * ffc->frame_rate_base);
|
// * fContext->frame_rate_base);
|
||||||
|
|
||||||
fOutputFrameRate = fOutputVideoFormat.field_rate;
|
fOutputFrameRate = fOutputVideoFormat.field_rate;
|
||||||
|
|
||||||
ffc->extradata = (uint8_t *)fExtraData;
|
fContext->extradata = (uint8_t *)fExtraData;
|
||||||
ffc->extradata_size = fExtraDataSize;
|
fContext->extradata_size = fExtraDataSize;
|
||||||
|
|
||||||
// if (fInputFormat.MetaDataSize() > 0) {
|
// if (fInputFormat.MetaDataSize() > 0) {
|
||||||
// ffc->extradata = (uint8_t *)fInputFormat.MetaData();
|
// fContext->extradata = (uint8_t *)fInputFormat.MetaData();
|
||||||
// ffc->extradata_size = fInputFormat.MetaDataSize();
|
// fContext->extradata_size = fInputFormat.MetaDataSize();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
TRACE("#### requested video format 0x%x\n",
|
TRACE(" requested video format 0x%x\n",
|
||||||
inout_format->u.raw_video.display.format);
|
inOutFormat->u.raw_video.display.format);
|
||||||
|
|
||||||
// make MediaPlayer happy (if not in rgb32 screen depth and no overlay,
|
// Make MediaPlayer happy (if not in rgb32 screen depth and no overlay,
|
||||||
// it will only ask for YCbCr, which DrawBitmap doesn't handle, so the
|
// it will only ask for YCbCr, which DrawBitmap doesn't handle, so the
|
||||||
// default colordepth is RGB32)
|
// default colordepth is RGB32).
|
||||||
if (inout_format->u.raw_video.display.format == B_YCbCr422)
|
if (inOutFormat->u.raw_video.display.format == B_YCbCr422)
|
||||||
fOutputVideoFormat.display.format = B_YCbCr422;
|
fOutputVideoFormat.display.format = B_YCbCr422;
|
||||||
else
|
else
|
||||||
fOutputVideoFormat.display.format = B_RGB32;
|
fOutputVideoFormat.display.format = B_RGB32;
|
||||||
|
|
||||||
// search for a pixel-format the codec handles
|
// Search for a pixel-format the codec handles
|
||||||
// XXX We should try this a couple of times until it succeeds, each time
|
// TODO: We should try this a couple of times until it succeeds, each
|
||||||
// XXX using another format pixel-format that is supported by the
|
// time using another pixel-format that is supported by the decoder.
|
||||||
// XXX decoder. But libavcodec doesn't seem to offer any way to tell the
|
// But libavcodec doesn't seem to offer any way to tell the decoder
|
||||||
// XXX decoder which format it should use.
|
// which format it should use.
|
||||||
conv_func = 0;
|
fFormatConversionFunc = 0;
|
||||||
for (int i = 0; i < 1; i++) { // iterate over supported codec formats
|
// Iterate over supported codec formats
|
||||||
|
for (int i = 0; i < 1; i++) {
|
||||||
// close any previous instance
|
// close any previous instance
|
||||||
if (fCodecInitDone) {
|
if (fCodecInitDone) {
|
||||||
fCodecInitDone = false;
|
fCodecInitDone = false;
|
||||||
avcodec_close(ffc);
|
avcodec_close(fContext);
|
||||||
}
|
}
|
||||||
// XXX set n-th ffc->pix_fmt here
|
// TODO: Set n-th fContext->pix_fmt here
|
||||||
if (avcodec_open(ffc, fCodec) >= 0) {
|
if (avcodec_open(fContext, fCodec) >= 0) {
|
||||||
fCodecInitDone = true;
|
fCodecInitDone = true;
|
||||||
|
|
||||||
conv_func = resolve_colorspace(fOutputVideoFormat.display.format, ffc->pix_fmt);
|
fFormatConversionFunc = resolve_colorspace(
|
||||||
|
fOutputVideoFormat.display.format, fContext->pix_fmt);
|
||||||
}
|
}
|
||||||
if (conv_func != 0)
|
if (fFormatConversionFunc != NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,8 +436,9 @@ AVCodecDecoder::NegotiateOutputFormat(media_format *inout_format)
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!conv_func) {
|
if (fFormatConversionFunc == NULL) {
|
||||||
TRACE("no conv_func found or decoder has not set the pixel format yet!\n");
|
TRACE("no pixel format conversion function found or decoder has "
|
||||||
|
"not set the pixel format yet!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fOutputVideoFormat.display.format == B_YCbCr422) {
|
if (fOutputVideoFormat.display.format == B_YCbCr422) {
|
||||||
@@ -380,53 +449,33 @@ AVCodecDecoder::NegotiateOutputFormat(media_format *inout_format)
|
|||||||
= 4 * fOutputVideoFormat.display.line_width;
|
= 4 * fOutputVideoFormat.display.line_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
inout_format->type = B_MEDIA_RAW_VIDEO;
|
inOutFormat->type = B_MEDIA_RAW_VIDEO;
|
||||||
inout_format->u.raw_video = fOutputVideoFormat;
|
inOutFormat->u.raw_video = fOutputVideoFormat;
|
||||||
|
|
||||||
inout_format->require_flags = 0;
|
inOutFormat->require_flags = 0;
|
||||||
inout_format->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
|
inOutFormat->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
|
||||||
|
|
||||||
#if DEBUG
|
#if TRACE_AV_CODEC
|
||||||
string_for_format(*inout_format, buffer, sizeof(buffer));
|
char buffer[1024];
|
||||||
TRACE("[%c] out_format=%s\n", isAudio?('a'):('v'), buffer);
|
string_for_format(*inOutFormat, buffer, sizeof(buffer));
|
||||||
#endif
|
TRACE("[v] outFormat = %s\n", buffer);
|
||||||
|
TRACE(" returned video format 0x%x\n",
|
||||||
TRACE("#### returned video format 0x%x\n",
|
inOutFormat->u.raw_video.display.format);
|
||||||
inout_format->u.raw_video.display.format);
|
#endif
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
AVCodecDecoder::Decode(void *out_buffer, int64 *out_frameCount,
|
AVCodecDecoder::_DecodeAudio(void* outBuffer, int64* outFrameCount,
|
||||||
media_header *mh, media_decode_info *info)
|
media_header* mediaHeader, media_decode_info* info)
|
||||||
{
|
{
|
||||||
const void *data;
|
// TRACE("audio start_time %.6f\n", mediaHeader->start_time / 1000000.0);
|
||||||
|
|
||||||
if (!fCodecInitDone)
|
char* output_buffer = (char*)outBuffer;
|
||||||
return B_BAD_VALUE;
|
*outFrameCount = 0;
|
||||||
|
while (*outFrameCount < fOutputFrameCount) {
|
||||||
#ifdef DO_PROFILING
|
|
||||||
bigtime_t prof_t1, prof_t2, prof_t3;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef UNREAL
|
|
||||||
set_thread_priority(find_thread(NULL), B_NORMAL_PRIORITY);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TRACE("[%c] AVCodecDecoder::Decode() for time %Ld\n", isAudio?('a'):('v'), fStartTime);
|
|
||||||
|
|
||||||
mh->start_time = fStartTime;
|
|
||||||
|
|
||||||
if (isAudio) {
|
|
||||||
|
|
||||||
// TRACE("audio start_time %.6f\n", mh->start_time / 1000000.0);
|
|
||||||
|
|
||||||
char *output_buffer = (char *)out_buffer;
|
|
||||||
*out_frameCount = 0;
|
|
||||||
while (*out_frameCount < fOutputFrameCount) {
|
|
||||||
if (fOutputBufferSize < 0) {
|
if (fOutputBufferSize < 0) {
|
||||||
TRACE("############ fOutputBufferSize %ld\n",
|
TRACE("############ fOutputBufferSize %ld\n",
|
||||||
fOutputBufferSize);
|
fOutputBufferSize);
|
||||||
@@ -439,21 +488,21 @@ AVCodecDecoder::Decode(void *out_buffer, int64 *out_frameCount,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fOutputBufferSize > 0) {
|
if (fOutputBufferSize > 0) {
|
||||||
int32 frames = min_c(fOutputFrameCount - *out_frameCount,
|
int32 frames = min_c(fOutputFrameCount - *outFrameCount,
|
||||||
fOutputBufferSize / fOutputFrameSize);
|
fOutputBufferSize / fOutputFrameSize);
|
||||||
memcpy(output_buffer, fOutputBuffer + fOutputBufferOffset,
|
memcpy(output_buffer, fOutputBuffer + fOutputBufferOffset,
|
||||||
frames * fOutputFrameSize);
|
frames * fOutputFrameSize);
|
||||||
fOutputBufferOffset += frames * fOutputFrameSize;
|
fOutputBufferOffset += frames * fOutputFrameSize;
|
||||||
fOutputBufferSize -= frames * fOutputFrameSize;
|
fOutputBufferSize -= frames * fOutputFrameSize;
|
||||||
output_buffer += frames * fOutputFrameSize;
|
output_buffer += frames * fOutputFrameSize;
|
||||||
*out_frameCount += frames;
|
*outFrameCount += frames;
|
||||||
fStartTime += (bigtime_t)((1000000LL * frames) / fOutputFrameRate);
|
fStartTime += (bigtime_t)((1000000LL * frames) / fOutputFrameRate);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (fChunkBufferSize == 0) {
|
if (fChunkBufferSize == 0) {
|
||||||
media_header chunk_mh;
|
media_header chunkMediaHeader;
|
||||||
status_t err;
|
status_t err;
|
||||||
err = GetNextChunk(&fChunkBuffer, &fChunkBufferSize, &chunk_mh);
|
err = GetNextChunk(&fChunkBuffer, &fChunkBufferSize, &chunkMediaHeader);
|
||||||
if (err == B_LAST_BUFFER_ERROR) {
|
if (err == B_LAST_BUFFER_ERROR) {
|
||||||
TRACE("Last Chunk with chunk size %ld\n",fChunkBufferSize);
|
TRACE("Last Chunk with chunk size %ld\n",fChunkBufferSize);
|
||||||
fChunkBufferSize = 0;
|
fChunkBufferSize = 0;
|
||||||
@@ -465,15 +514,15 @@ AVCodecDecoder::Decode(void *out_buffer, int64 *out_frameCount,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fChunkBufferOffset = 0;
|
fChunkBufferOffset = 0;
|
||||||
fStartTime = chunk_mh.start_time;
|
fStartTime = chunkMediaHeader.start_time;
|
||||||
if (*out_frameCount == 0)
|
if (*outFrameCount == 0)
|
||||||
mh->start_time = chunk_mh.start_time;
|
mediaHeader->start_time = chunkMediaHeader.start_time;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (fOutputBufferSize == 0) {
|
if (fOutputBufferSize == 0) {
|
||||||
int len;
|
int len;
|
||||||
int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
||||||
len = avcodec_decode_audio2(ffc, (short *)fOutputBuffer,
|
len = avcodec_decode_audio2(fContext, (short *)fOutputBuffer,
|
||||||
&out_size, (uint8_t*)fChunkBuffer + fChunkBufferOffset,
|
&out_size, (uint8_t*)fChunkBuffer + fChunkBufferOffset,
|
||||||
fChunkBufferSize);
|
fChunkBufferSize);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
@@ -493,111 +542,137 @@ AVCodecDecoder::Decode(void *out_buffer, int64 *out_frameCount,
|
|||||||
fOutputBufferSize = out_size;
|
fOutputBufferSize = out_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fFrame += *out_frameCount;
|
fFrame += *outFrameCount;
|
||||||
|
|
||||||
// TRACE("Played %Ld frames at time %Ld\n",*out_frameCount, mh->start_time);
|
// TRACE("Played %Ld frames at time %Ld\n",*outFrameCount, mediaHeader->start_time);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
} else { // Video
|
|
||||||
|
|
||||||
media_header chunk_mh;
|
status_t
|
||||||
status_t err;
|
AVCodecDecoder::_DecodeVideo(void* outBuffer, int64* outFrameCount,
|
||||||
|
media_header* mediaHeader, media_decode_info* info)
|
||||||
|
{
|
||||||
|
bool firstRun = true;
|
||||||
|
while (true) {
|
||||||
|
const void* data;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
media_header chunkMediaHeader;
|
||||||
err = GetNextChunk(&data, &size, &chunk_mh);
|
status_t err = GetNextChunk(&data, &size, &chunkMediaHeader);
|
||||||
if (err != B_OK) {
|
if (err != B_OK) {
|
||||||
TRACE("AVCodecDecoder::Decode(): error 0x%08lx from GetNextChunk()\n", err);
|
TRACE("AVCodecDecoder::_DecodeVideo(): error from "
|
||||||
|
"GetNextChunk(): %s\n", strerror(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
if (firstRun) {
|
||||||
|
firstRun = false;
|
||||||
|
|
||||||
mh->type = B_MEDIA_RAW_VIDEO;
|
mediaHeader->type = B_MEDIA_RAW_VIDEO;
|
||||||
// mh->start_time = chunk_mh.start_time;
|
// mediaHeader->start_time = chunkMediaHeader.start_time;
|
||||||
mh->file_pos = 0;
|
mediaHeader->file_pos = 0;
|
||||||
mh->orig_size = 0;
|
mediaHeader->orig_size = 0;
|
||||||
mh->u.raw_video.field_gamma = 1.0;
|
mediaHeader->u.raw_video.field_gamma = 1.0;
|
||||||
mh->u.raw_video.field_sequence = fFrame;
|
mediaHeader->u.raw_video.field_sequence = fFrame;
|
||||||
mh->u.raw_video.field_number = 0;
|
mediaHeader->u.raw_video.field_number = 0;
|
||||||
mh->u.raw_video.pulldown_number = 0;
|
mediaHeader->u.raw_video.pulldown_number = 0;
|
||||||
mh->u.raw_video.first_active_line = 1;
|
mediaHeader->u.raw_video.first_active_line = 1;
|
||||||
mh->u.raw_video.line_count = fOutputVideoFormat.display.line_count;
|
mediaHeader->u.raw_video.line_count
|
||||||
|
= fOutputVideoFormat.display.line_count;
|
||||||
|
|
||||||
TRACE("[%c] start_time=%02d:%02d.%02d field_sequence=%lu\n",
|
TRACE("[v] start_time=%02d:%02d.%02d field_sequence=%lu\n",
|
||||||
isAudio ? ('a') : ('v'),
|
int((mediaHeader->start_time / 60000000) % 60),
|
||||||
int((mh->start_time / 60000000) % 60),
|
int((mediaHeader->start_time / 1000000) % 60),
|
||||||
int((mh->start_time / 1000000) % 60),
|
int((mediaHeader->start_time / 10000) % 100),
|
||||||
int((mh->start_time / 10000) % 100),
|
mediaHeader->u.raw_video.field_sequence);
|
||||||
mh->u.raw_video.field_sequence);
|
|
||||||
|
|
||||||
#ifdef DO_PROFILING
|
|
||||||
prof_t1 = system_time();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int got_picture = 0;
|
|
||||||
int len;
|
|
||||||
len = avcodec_decode_video(ffc, ffpicture, &got_picture,
|
|
||||||
(uint8_t *)data, size);
|
|
||||||
|
|
||||||
//TRACE("FFDEC: PTS = %d:%d:%d.%d - ffc->frame_number = %ld "
|
|
||||||
// "ffc->frame_rate = %ld\n", (int)(ffc->pts / (60*60*1000000)),
|
|
||||||
// (int)(ffc->pts / (60*1000000)), (int)(ffc->pts / (1000000)),
|
|
||||||
// (int)(ffc->pts % 1000000), ffc->frame_number, ffc->frame_rate);
|
|
||||||
//TRACE("FFDEC: PTS = %d:%d:%d.%d - ffc->frame_number = %ld "
|
|
||||||
// "ffc->frame_rate = %ld\n", (int)(ffpicture->pts / (60*60*1000000)),
|
|
||||||
// (int)(ffpicture->pts / (60*1000000)), (int)(ffpicture->pts / (1000000)),
|
|
||||||
// (int)(ffpicture->pts % 1000000), ffc->frame_number, ffc->frame_rate);
|
|
||||||
|
|
||||||
if (len < 0) {
|
|
||||||
printf("[%c] AVCodecDecoder: error in decoding frame %lld\n",
|
|
||||||
isAudio?('a'):('v'), *out_frameCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (got_picture) {
|
#if DO_PROFILING
|
||||||
#ifdef DO_PROFILING
|
bigtime_t startTime = system_time();
|
||||||
prof_t2 = system_time();
|
#endif
|
||||||
|
|
||||||
|
// NOTE: In the FFmpeg code example I've read, the length returned by
|
||||||
|
// avcodec_decode_video() is completely ignored. Furthermore, the
|
||||||
|
// 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.
|
||||||
|
int gotPicture = 0;
|
||||||
|
int len = avcodec_decode_video(fContext, fInputPicture, &gotPicture,
|
||||||
|
(uint8_t*)data, size);
|
||||||
|
if (len < 0) {
|
||||||
|
TRACE("[v] AVCodecDecoder: error in decoding frame %lld: %d\n",
|
||||||
|
fFrame, len);
|
||||||
|
// return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TRACE("FFDEC: PTS = %d:%d:%d.%d - fContext->frame_number = %ld "
|
||||||
|
// "fContext->frame_rate = %ld\n", (int)(fContext->pts / (60*60*1000000)),
|
||||||
|
// (int)(fContext->pts / (60*1000000)), (int)(fContext->pts / (1000000)),
|
||||||
|
// (int)(fContext->pts % 1000000), fContext->frame_number,
|
||||||
|
// fContext->frame_rate);
|
||||||
|
//TRACE("FFDEC: PTS = %d:%d:%d.%d - fContext->frame_number = %ld "
|
||||||
|
// "fContext->frame_rate = %ld\n",
|
||||||
|
// (int)(fInputPicture->pts / (60*60*1000000)),
|
||||||
|
// (int)(fInputPicture->pts / (60*1000000)),
|
||||||
|
// (int)(fInputPicture->pts / (1000000)),
|
||||||
|
// (int)(fInputPicture->pts % 1000000), fContext->frame_number,
|
||||||
|
// fContext->frame_rate);
|
||||||
|
|
||||||
|
if (gotPicture) {
|
||||||
|
#if DO_PROFILING
|
||||||
|
bigtime_t formatConversionStart = system_time();
|
||||||
#endif
|
#endif
|
||||||
// TRACE("ONE FRAME OUT !! len=%d size=%ld (%s)\n", len, size,
|
// TRACE("ONE FRAME OUT !! len=%d size=%ld (%s)\n", len, size,
|
||||||
// pixfmt_to_string(ffc->pix_fmt));
|
// pixfmt_to_string(fContext->pix_fmt));
|
||||||
|
|
||||||
// Some decoders do not set pix_fmt until they have decoded 1 frame
|
// Some decoders do not set pix_fmt until they have decoded 1 frame
|
||||||
if (conv_func == 0) {
|
if (fFormatConversionFunc == NULL) {
|
||||||
conv_func = resolve_colorspace(fOutputVideoFormat.display.format, ffc->pix_fmt);
|
fFormatConversionFunc = resolve_colorspace(
|
||||||
|
fOutputVideoFormat.display.format, fContext->pix_fmt);
|
||||||
}
|
}
|
||||||
opicture->data[0] = (uint8_t *)out_buffer;
|
fOutputPicture->data[0] = (uint8_t*)outBuffer;
|
||||||
opicture->linesize[0] = fOutputVideoFormat.display.bytes_per_row;
|
fOutputPicture->linesize[0]
|
||||||
|
= fOutputVideoFormat.display.bytes_per_row;
|
||||||
|
|
||||||
if (conv_func) {
|
if (fFormatConversionFunc != NULL) {
|
||||||
(*conv_func)(ffpicture, opicture,
|
(*fFormatConversionFunc)(fInputPicture, fOutputPicture,
|
||||||
fOutputVideoFormat.display.line_width,
|
fOutputVideoFormat.display.line_width,
|
||||||
fOutputVideoFormat.display.line_count);
|
fOutputVideoFormat.display.line_count);
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
dump_ffframe(ffpicture, "ffpict");
|
dump_ffframe(fInputPicture, "ffpict");
|
||||||
// dump_ffframe(opicture, "opict");
|
// dump_ffframe(fOutputPicture, "opict");
|
||||||
#endif
|
#endif
|
||||||
*out_frameCount = 1;
|
*outFrameCount = 1;
|
||||||
fFrame++;
|
fFrame++;
|
||||||
|
|
||||||
#ifdef DO_PROFILING
|
#if DO_PROFILING
|
||||||
prof_t3 = system_time();
|
bigtime_t doneTime = system_time();
|
||||||
diff1 += prof_t2 - prof_t1;
|
decodingTime += formatConversionStart - startTime;
|
||||||
diff2 += prof_t3 - prof_t2;
|
conversionTime += doneTime - formatConversionStart;
|
||||||
prof_cnt++;
|
profileCounter++;
|
||||||
if (!(fFrame % 10)) {
|
if (!(fFrame % 10)) {
|
||||||
if (info) {
|
if (info) {
|
||||||
TRACE("[%c] profile: d1 = %lld, d2 = %lld (%Ld) required %Ld\n",
|
TRACE("[v] profile: d1 = %lld, d2 = %lld (%Ld) required "
|
||||||
isAudio?('a'):('v'), diff1/prof_cnt, diff2/prof_cnt,
|
"%Ld\n",
|
||||||
|
decodingTime / profileCounter,
|
||||||
|
conversionTime / profileCounter,
|
||||||
fFrame, info->time_to_decode);
|
fFrame, info->time_to_decode);
|
||||||
} else {
|
} else {
|
||||||
TRACE("[%c] profile: d1 = %lld, d2 = %lld (%Ld) required %Ld\n",
|
TRACE("[v] profile: d1 = %lld, d2 = %lld (%Ld) required "
|
||||||
isAudio?('a'):('v'), diff1/prof_cnt, diff2/prof_cnt,
|
"%Ld\n",
|
||||||
|
decodingTime / profileCounter,
|
||||||
|
conversionTime / profileCounter,
|
||||||
fFrame, bigtime_t(1000000LL / fOutputFrameRate));
|
fFrame, bigtime_t(1000000LL / fOutputFrameRate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fStartTime = (bigtime_t) (1000000LL * fFrame / fOutputFrameRate);
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
} else {
|
||||||
|
TRACE("frame %lld - no picture yet, len: %d, chunk size: %ld\n",
|
||||||
|
fFrame, len, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public:
|
|||||||
const void* infoBuffer, size_t infoSize);
|
const void* infoBuffer, size_t infoSize);
|
||||||
|
|
||||||
virtual status_t NegotiateOutputFormat(
|
virtual status_t NegotiateOutputFormat(
|
||||||
media_format* outputFormat);
|
media_format* inOutFormat);
|
||||||
|
|
||||||
virtual status_t Decode(void* outBuffer, int64* outFrameCount,
|
virtual status_t Decode(void* outBuffer, int64* outFrameCount,
|
||||||
media_header* mediaHeader,
|
media_header* mediaHeader,
|
||||||
@@ -43,31 +43,44 @@ public:
|
|||||||
bigtime_t* time);
|
bigtime_t* time);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
|
status_t _NegotiateAudioOutputFormat(
|
||||||
|
media_format* inOutFormat);
|
||||||
|
|
||||||
|
status_t _NegotiateVideoOutputFormat(
|
||||||
|
media_format* inOutFormat);
|
||||||
|
|
||||||
|
status_t _DecodeAudio(void* outBuffer,
|
||||||
|
int64* outFrameCount,
|
||||||
|
media_header* mediaHeader,
|
||||||
|
media_decode_info* info);
|
||||||
|
|
||||||
|
status_t _DecodeVideo(void* outBuffer,
|
||||||
|
int64* outFrameCount,
|
||||||
|
media_header* mediaHeader,
|
||||||
|
media_decode_info* info);
|
||||||
|
|
||||||
|
|
||||||
media_header fHeader;
|
media_header fHeader;
|
||||||
media_decode_info fInfo;
|
media_decode_info fInfo;
|
||||||
|
|
||||||
// friend class avCodecInputStream;
|
|
||||||
|
|
||||||
private:
|
|
||||||
media_format fInputFormat;
|
media_format fInputFormat;
|
||||||
media_raw_video_format fOutputVideoFormat;
|
media_raw_video_format fOutputVideoFormat;
|
||||||
|
|
||||||
int64 fFrame;
|
int64 fFrame;
|
||||||
bool isAudio;
|
bool fIsAudio;
|
||||||
|
|
||||||
int ffcodec_index_in_table;
|
int fCodecIndexInTable;
|
||||||
// helps to find codecpretty
|
// helps to find codecpretty
|
||||||
|
|
||||||
// ffmpeg related datas
|
// FFmpeg related members
|
||||||
AVCodec* fCodec;
|
AVCodec* fCodec;
|
||||||
AVCodecContext* ffc;
|
AVCodecContext* fContext;
|
||||||
AVFrame* ffpicture;
|
AVFrame* fInputPicture;
|
||||||
AVFrame* opicture;
|
AVFrame* fOutputPicture;
|
||||||
|
|
||||||
bool fCodecInitDone;
|
bool fCodecInitDone;
|
||||||
|
|
||||||
gfx_convert_func conv_func; // colorspace convert func
|
gfx_convert_func fFormatConversionFunc;
|
||||||
|
|
||||||
char* fExtraData;
|
char* fExtraData;
|
||||||
int fExtraDataSize;
|
int fExtraDataSize;
|
||||||
@@ -76,7 +89,8 @@ private:
|
|||||||
bigtime_t fStartTime;
|
bigtime_t fStartTime;
|
||||||
int32 fOutputFrameCount;
|
int32 fOutputFrameCount;
|
||||||
float fOutputFrameRate;
|
float fOutputFrameRate;
|
||||||
int fOutputFrameSize; // sample size * channel count
|
int fOutputFrameSize;
|
||||||
|
// sample size * channel count
|
||||||
|
|
||||||
const void* fChunkBuffer;
|
const void* fChunkBuffer;
|
||||||
int32 fChunkBufferOffset;
|
int32 fChunkBufferOffset;
|
||||||
|
|||||||
Reference in New Issue
Block a user