Encoder:
* Fleshed out the Encoder API to support parameter setters/getters and returning a BView for configuration. (Not yet sure if this is a good idea.) BMediaTrack: * Implemented all but one of the unimplemented methods in BMediaTrack. It should be working as far as that class is concerned, unless I missed some of the vision. ReplaceFrames() remains a stub, added a comment on why it probably stays that way. * Release the Encoder reference in the destructor. FFmpeg plugin: * Refactoring to delay opening the AVCodec until encoding the first chunk, so that we can still adjust parameters. * Support adjusting parameters via [Set|Get]EncodeParameters(). Currently, only quality is supported, added TODOs about supporting the bit_rate setup versus the automatically calculated bit_rate. * Extended EncoderDescription by a bit_rate scale. The Encoder calculates the raw bitrate needed by the current media format, and then divides that number by the specific codec's bit_rate_scale, while taking into account the desired quality. This seems to work very well already (tested with MPEG4), although a lot more parameters could be specified for libavcodec, depending on the desired quality. * Enabled the ogg muxer in libavformat, although it is currently still disabled in MuxerTable.cpp, because it rejects unknown codecs. Added TODO to this effect. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32124 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -8,11 +8,10 @@
|
|||||||
|
|
||||||
#include <MediaTrack.h>
|
#include <MediaTrack.h>
|
||||||
#include <MediaFormats.h>
|
#include <MediaFormats.h>
|
||||||
|
#include <View.h>
|
||||||
#include "MediaPlugin.h"
|
#include "MediaPlugin.h"
|
||||||
|
|
||||||
|
|
||||||
class AddOnManager;
|
|
||||||
|
|
||||||
namespace BPrivate { namespace media {
|
namespace BPrivate { namespace media {
|
||||||
|
|
||||||
class PluginManager;
|
class PluginManager;
|
||||||
@@ -56,10 +55,20 @@ public:
|
|||||||
virtual status_t AddTrackInfo(uint32 code, const void* data,
|
virtual status_t AddTrackInfo(uint32 code, const void* data,
|
||||||
size_t size, uint32 flags = 0);
|
size_t size, uint32 flags = 0);
|
||||||
|
|
||||||
|
// Ownership of the BView and BParameterWeb remain with the Encoder.
|
||||||
|
// A window embedding the view must remove it before it is destroyed.
|
||||||
|
virtual BView* ParameterView();
|
||||||
|
|
||||||
|
virtual BParameterWeb* ParameterWeb();
|
||||||
|
virtual status_t GetParameterValue(int32 id, void* value,
|
||||||
|
size_t* size) const;
|
||||||
|
virtual status_t SetParameterValue(int32 id, const void* value,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
virtual status_t GetEncodeParameters(
|
virtual status_t GetEncodeParameters(
|
||||||
encode_parameters* parameters) const;
|
encode_parameters* parameters) const;
|
||||||
virtual status_t SetEncodeParameters(
|
virtual status_t SetEncodeParameters(
|
||||||
encode_parameters* parameters) const;
|
encode_parameters* parameters);
|
||||||
|
|
||||||
virtual status_t Encode(const void* buffer, int64 frameCount,
|
virtual status_t Encode(const void* buffer, int64 frameCount,
|
||||||
media_encode_info* info) = 0;
|
media_encode_info* info) = 0;
|
||||||
@@ -73,19 +82,36 @@ public:
|
|||||||
virtual status_t Perform(perform_code code, void* data);
|
virtual status_t Perform(perform_code code, void* data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void _ReservedEncoder1();
|
|
||||||
virtual void _ReservedEncoder2();
|
|
||||||
virtual void _ReservedEncoder3();
|
|
||||||
virtual void _ReservedEncoder4();
|
|
||||||
virtual void _ReservedEncoder5();
|
|
||||||
|
|
||||||
ChunkWriter* fChunkWriter;
|
ChunkWriter* fChunkWriter;
|
||||||
|
|
||||||
// needed for plug-in reference count management
|
// needed for plug-in reference count management
|
||||||
friend class PluginManager;
|
friend class PluginManager;
|
||||||
MediaPlugin* fMediaPlugin;
|
MediaPlugin* fMediaPlugin;
|
||||||
|
|
||||||
uint32 fReserved[5];
|
private:
|
||||||
|
// FBC padding
|
||||||
|
uint32 fReserved[20];
|
||||||
|
|
||||||
|
virtual void _ReservedEncoder1();
|
||||||
|
virtual void _ReservedEncoder2();
|
||||||
|
virtual void _ReservedEncoder3();
|
||||||
|
virtual void _ReservedEncoder4();
|
||||||
|
virtual void _ReservedEncoder5();
|
||||||
|
virtual void _ReservedEncoder6();
|
||||||
|
virtual void _ReservedEncoder7();
|
||||||
|
virtual void _ReservedEncoder8();
|
||||||
|
virtual void _ReservedEncoder9();
|
||||||
|
virtual void _ReservedEncoder10();
|
||||||
|
virtual void _ReservedEncoder11();
|
||||||
|
virtual void _ReservedEncoder12();
|
||||||
|
virtual void _ReservedEncoder13();
|
||||||
|
virtual void _ReservedEncoder14();
|
||||||
|
virtual void _ReservedEncoder15();
|
||||||
|
virtual void _ReservedEncoder16();
|
||||||
|
virtual void _ReservedEncoder17();
|
||||||
|
virtual void _ReservedEncoder18();
|
||||||
|
virtual void _ReservedEncoder19();
|
||||||
|
virtual void _ReservedEncoder20();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,12 +30,13 @@ extern "C" {
|
|||||||
static const size_t kDefaultChunkBufferSize = 2 * 1024 * 1024;
|
static const size_t kDefaultChunkBufferSize = 2 * 1024 * 1024;
|
||||||
|
|
||||||
|
|
||||||
AVCodecEncoder::AVCodecEncoder(uint32 codecID)
|
AVCodecEncoder::AVCodecEncoder(uint32 codecID, int bitRateScale)
|
||||||
:
|
:
|
||||||
Encoder(),
|
Encoder(),
|
||||||
|
fBitRateScale(bitRateScale),
|
||||||
fCodec(NULL),
|
fCodec(NULL),
|
||||||
fContext(avcodec_alloc_context()),
|
fContext(avcodec_alloc_context()),
|
||||||
fCodecInitDone(false),
|
fCodecInitStatus(CODEC_INIT_NEEDED),
|
||||||
|
|
||||||
fFrame(avcodec_alloc_frame()),
|
fFrame(avcodec_alloc_frame()),
|
||||||
fSwsContext(NULL),
|
fSwsContext(NULL),
|
||||||
@@ -52,6 +53,11 @@ AVCodecEncoder::AVCodecEncoder(uint32 codecID)
|
|||||||
memset(&fInputFormat, 0, sizeof(media_format));
|
memset(&fInputFormat, 0, sizeof(media_format));
|
||||||
|
|
||||||
av_fifo_init(&fAudioFifo, 0);
|
av_fifo_init(&fAudioFifo, 0);
|
||||||
|
|
||||||
|
// Initial parameters, so we know if the user changed them
|
||||||
|
fEncodeParameters.avg_field_size = 0;
|
||||||
|
fEncodeParameters.max_field_size = 0;
|
||||||
|
fEncodeParameters.quality = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -59,8 +65,7 @@ AVCodecEncoder::~AVCodecEncoder()
|
|||||||
{
|
{
|
||||||
TRACE("AVCodecEncoder::~AVCodecEncoder()\n");
|
TRACE("AVCodecEncoder::~AVCodecEncoder()\n");
|
||||||
|
|
||||||
if (fCodecInitDone)
|
_CloseCodecIfNeeded();
|
||||||
avcodec_close(fContext);
|
|
||||||
|
|
||||||
sws_freeContext(fSwsContext);
|
sws_freeContext(fSwsContext);
|
||||||
|
|
||||||
@@ -119,15 +124,118 @@ AVCodecEncoder::SetUp(const media_format* inputFormat)
|
|||||||
if (inputFormat == NULL)
|
if (inputFormat == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
if (fCodecInitDone) {
|
_CloseCodecIfNeeded();
|
||||||
fCodecInitDone = false;
|
|
||||||
avcodec_close(fContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
fInputFormat = *inputFormat;
|
fInputFormat = *inputFormat;
|
||||||
fFramesWritten = 0;
|
fFramesWritten = 0;
|
||||||
|
|
||||||
|
return _Setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AVCodecEncoder::GetEncodeParameters(encode_parameters* parameters) const
|
||||||
|
{
|
||||||
|
TRACE("AVCodecEncoder::GetEncodeParameters(%p)\n", parameters);
|
||||||
|
|
||||||
|
// TODO: Implement maintaining an automatically calculated bit_rate versus
|
||||||
|
// a user specified (via SetEncodeParameters()) bit_rate. At this point, the
|
||||||
|
// fContext->bit_rate may not yet have been specified (_Setup() was never
|
||||||
|
// called yet). So it cannot work like the code below, but in any case, it's
|
||||||
|
// showing how to convert between the values (Albeit untested).
|
||||||
|
// int avgBytesPerSecond = fContext->bit_rate / 8;
|
||||||
|
// int maxBytesPerSecond = (fContext->bit_rate
|
||||||
|
// + fContext->bit_rate_tolerance) / 8;
|
||||||
|
//
|
||||||
|
// if (fInputFormat.type == B_MEDIA_RAW_AUDIO) {
|
||||||
|
// fEncodeParameters.avg_field_size = (int32)(avgBytesPerSecond
|
||||||
|
// / fInputFormat.u.raw_audio.frame_rate);
|
||||||
|
// fEncodeParameters.max_field_size = (int32)(maxBytesPerSecond
|
||||||
|
// / fInputFormat.u.raw_audio.frame_rate);
|
||||||
|
// } else if (fInputFormat.type == B_MEDIA_RAW_VIDEO) {
|
||||||
|
// fEncodeParameters.avg_field_size = (int32)(avgBytesPerSecond
|
||||||
|
// / fInputFormat.u.raw_video.field_rate);
|
||||||
|
// fEncodeParameters.max_field_size = (int32)(maxBytesPerSecond
|
||||||
|
// / fInputFormat.u.raw_video.field_rate);
|
||||||
|
// }
|
||||||
|
|
||||||
|
parameters->quality = fEncodeParameters.quality;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AVCodecEncoder::SetEncodeParameters(encode_parameters* parameters)
|
||||||
|
{
|
||||||
|
TRACE("AVCodecEncoder::SetEncodeParameters(%p)\n", parameters);
|
||||||
|
|
||||||
|
if (fFramesWritten > 0)
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
fEncodeParameters.quality = parameters->quality;
|
||||||
|
TRACE(" quality: %.1f\n", parameters->quality);
|
||||||
|
|
||||||
|
// TODO: Auto-bit_rate versus user supplied. See above.
|
||||||
|
// int avgBytesPerSecond = 0;
|
||||||
|
// int maxBytesPerSecond = 0;
|
||||||
|
//
|
||||||
|
// if (fInputFormat.type == B_MEDIA_RAW_AUDIO) {
|
||||||
|
// avgBytesPerSecond = (int)(parameters->avg_field_size
|
||||||
|
// * fInputFormat.u.raw_audio.frame_rate);
|
||||||
|
// maxBytesPerSecond = (int)(parameters->max_field_size
|
||||||
|
// * fInputFormat.u.raw_audio.frame_rate);
|
||||||
|
// } else if (fInputFormat.type == B_MEDIA_RAW_VIDEO) {
|
||||||
|
// avgBytesPerSecond = (int)(parameters->avg_field_size
|
||||||
|
// * fInputFormat.u.raw_video.field_rate);
|
||||||
|
// maxBytesPerSecond = (int)(parameters->max_field_size
|
||||||
|
// * fInputFormat.u.raw_video.field_rate);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (maxBytesPerSecond < avgBytesPerSecond)
|
||||||
|
// maxBytesPerSecond = avgBytesPerSecond;
|
||||||
|
//
|
||||||
|
// // Reset these, so we can tell the difference between uninitialized
|
||||||
|
// // and initialized...
|
||||||
|
// if (avgBytesPerSecond > 0) {
|
||||||
|
// fContext->bit_rate = avgBytesPerSecond * 8;
|
||||||
|
// fContext->bit_rate_tolerance = (maxBytesPerSecond
|
||||||
|
// - avgBytesPerSecond) * 8;
|
||||||
|
// fBitRateControlledByUser = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
return _Setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AVCodecEncoder::Encode(const void* buffer, int64 frameCount,
|
||||||
|
media_encode_info* info)
|
||||||
|
{
|
||||||
|
TRACE("AVCodecEncoder::Encode(%p, %lld, %p)\n", buffer, frameCount, info);
|
||||||
|
|
||||||
|
if (!_OpenCodecIfNeeded())
|
||||||
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
if (fInputFormat.type == B_MEDIA_RAW_AUDIO)
|
||||||
|
return _EncodeAudio(buffer, frameCount, info);
|
||||||
|
else if (fInputFormat.type == B_MEDIA_RAW_VIDEO)
|
||||||
|
return _EncodeVideo(buffer, frameCount, info);
|
||||||
|
else
|
||||||
|
return B_NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AVCodecEncoder::_Setup()
|
||||||
|
{
|
||||||
|
TRACE("AVCodecEncoder::_Setup\n");
|
||||||
|
|
||||||
if (fInputFormat.type == B_MEDIA_RAW_VIDEO) {
|
if (fInputFormat.type == B_MEDIA_RAW_VIDEO) {
|
||||||
|
TRACE(" B_MEDIA_RAW_VIDEO\n");
|
||||||
// frame rate
|
// frame rate
|
||||||
fContext->time_base.den = (int)fInputFormat.u.raw_video.field_rate;
|
fContext->time_base.den = (int)fInputFormat.u.raw_video.field_rate;
|
||||||
fContext->time_base.num = 1;
|
fContext->time_base.num = 1;
|
||||||
@@ -144,7 +252,15 @@ AVCodecEncoder::SetUp(const media_format* inputFormat)
|
|||||||
// fContext->rc_max_rate = 0;
|
// fContext->rc_max_rate = 0;
|
||||||
// fContext->rc_min_rate = 0;
|
// fContext->rc_min_rate = 0;
|
||||||
// TODO: Try to calculate a good bit rate...
|
// TODO: Try to calculate a good bit rate...
|
||||||
fContext->bit_rate = 800000;
|
int rawBitRate = (int)(fContext->width * fContext->height * 2
|
||||||
|
* fInputFormat.u.raw_video.field_rate) * 8;
|
||||||
|
int wantedBitRate = (int)(rawBitRate / fBitRateScale
|
||||||
|
* fEncodeParameters.quality);
|
||||||
|
TRACE(" rawBitRate: %d, wantedBitRate: %d (%.1f)\n", rawBitRate,
|
||||||
|
wantedBitRate, fEncodeParameters.quality);
|
||||||
|
// TODO: Support letting the user overwrite this via
|
||||||
|
// SetEncodeParameters(). See comments there...
|
||||||
|
fContext->bit_rate = wantedBitRate;
|
||||||
|
|
||||||
// Pixel aspect ratio
|
// Pixel aspect ratio
|
||||||
fContext->sample_aspect_ratio.num
|
fContext->sample_aspect_ratio.num
|
||||||
@@ -188,6 +304,7 @@ AVCodecEncoder::SetUp(const media_format* inputFormat)
|
|||||||
fContext->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);
|
fContext->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);
|
||||||
|
|
||||||
} else if (fInputFormat.type == B_MEDIA_RAW_AUDIO) {
|
} else if (fInputFormat.type == B_MEDIA_RAW_AUDIO) {
|
||||||
|
TRACE(" B_MEDIA_RAW_AUDIO\n");
|
||||||
// frame rate
|
// frame rate
|
||||||
fContext->sample_rate = (int)fInputFormat.u.raw_audio.frame_rate;
|
fContext->sample_rate = (int)fInputFormat.u.raw_audio.frame_rate;
|
||||||
// NOTE: From the output_example.c, it looks like we are not supposed
|
// NOTE: From the output_example.c, it looks like we are not supposed
|
||||||
@@ -252,6 +369,7 @@ AVCodecEncoder::SetUp(const media_format* inputFormat)
|
|||||||
fContext->channel_layout = fInputFormat.u.raw_audio.channel_mask;
|
fContext->channel_layout = fInputFormat.u.raw_audio.channel_mask;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
TRACE(" UNSUPPORTED MEDIA TYPE!\n");
|
||||||
return B_NOT_SUPPORTED;
|
return B_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,55 +384,46 @@ AVCodecEncoder::SetUp(const media_format* inputFormat)
|
|||||||
fContext->mb_decision = 2;
|
fContext->mb_decision = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unfortunately, we may fail later, when we try to open the codec
|
||||||
|
// for real... but we need to delay this because we still allow
|
||||||
|
// parameter/quality changes.
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
AVCodecEncoder::_OpenCodecIfNeeded()
|
||||||
|
{
|
||||||
|
if (fCodecInitStatus == CODEC_INIT_DONE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (fCodecInitStatus == CODEC_INIT_FAILED)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Open the codec
|
// Open the codec
|
||||||
int result = avcodec_open(fContext, fCodec);
|
int result = avcodec_open(fContext, fCodec);
|
||||||
fCodecInitDone = (result >= 0);
|
if (result >= 0)
|
||||||
|
fCodecInitStatus = CODEC_INIT_DONE;
|
||||||
|
else
|
||||||
|
fCodecInitStatus = CODEC_INIT_FAILED;
|
||||||
|
|
||||||
TRACE(" avcodec_open(): %d\n", result);
|
TRACE(" avcodec_open(): %d\n", result);
|
||||||
|
|
||||||
return fCodecInitDone ? B_OK : B_ERROR;
|
return fCodecInitStatus == CODEC_INIT_DONE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
void
|
||||||
AVCodecEncoder::GetEncodeParameters(encode_parameters* parameters) const
|
AVCodecEncoder::_CloseCodecIfNeeded()
|
||||||
{
|
{
|
||||||
TRACE("AVCodecEncoder::GetEncodeParameters(%p)\n", parameters);
|
if (fCodecInitStatus == CODEC_INIT_DONE) {
|
||||||
|
avcodec_close(fContext);
|
||||||
return B_NOT_SUPPORTED;
|
fCodecInitStatus = CODEC_INIT_NEEDED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
AVCodecEncoder::SetEncodeParameters(encode_parameters* parameters) const
|
|
||||||
{
|
|
||||||
TRACE("AVCodecEncoder::SetEncodeParameters(%p)\n", parameters);
|
|
||||||
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
AVCodecEncoder::Encode(const void* buffer, int64 frameCount,
|
|
||||||
media_encode_info* info)
|
|
||||||
{
|
|
||||||
TRACE("AVCodecEncoder::Encode(%p, %lld, %p)\n", buffer, frameCount, info);
|
|
||||||
|
|
||||||
if (!fCodecInitDone)
|
|
||||||
return B_NO_INIT;
|
|
||||||
|
|
||||||
if (fInputFormat.type == B_MEDIA_RAW_AUDIO)
|
|
||||||
return _EncodeAudio(buffer, frameCount, info);
|
|
||||||
else if (fInputFormat.type == B_MEDIA_RAW_VIDEO)
|
|
||||||
return _EncodeVideo(buffer, frameCount, info);
|
|
||||||
else
|
|
||||||
return B_NO_INIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
static const int64 kNoPTSValue = 0x8000000000000000LL;
|
static const int64 kNoPTSValue = 0x8000000000000000LL;
|
||||||
// NOTE: For some reasons, I have trouble with the avcodec.h define:
|
// NOTE: For some reasons, I have trouble with the avcodec.h define:
|
||||||
// #define AV_NOPTS_VALUE INT64_C(0x8000000000000000)
|
// #define AV_NOPTS_VALUE INT64_C(0x8000000000000000)
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ extern "C" {
|
|||||||
|
|
||||||
class AVCodecEncoder : public Encoder {
|
class AVCodecEncoder : public Encoder {
|
||||||
public:
|
public:
|
||||||
AVCodecEncoder(uint32 codecID);
|
AVCodecEncoder(uint32 codecID,
|
||||||
|
int bitRateScale);
|
||||||
|
|
||||||
virtual ~AVCodecEncoder();
|
virtual ~AVCodecEncoder();
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ public:
|
|||||||
virtual status_t GetEncodeParameters(
|
virtual status_t GetEncodeParameters(
|
||||||
encode_parameters* parameters) const;
|
encode_parameters* parameters) const;
|
||||||
virtual status_t SetEncodeParameters(
|
virtual status_t SetEncodeParameters(
|
||||||
encode_parameters* parameters) const;
|
encode_parameters* parameters);
|
||||||
|
|
||||||
virtual status_t Encode(const void* buffer, int64 frameCount,
|
virtual status_t Encode(const void* buffer, int64 frameCount,
|
||||||
media_encode_info* info);
|
media_encode_info* info);
|
||||||
@@ -42,6 +43,11 @@ public:
|
|||||||
// codec buffer size.
|
// codec buffer size.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
status_t _Setup();
|
||||||
|
|
||||||
|
bool _OpenCodecIfNeeded();
|
||||||
|
void _CloseCodecIfNeeded();
|
||||||
|
|
||||||
status_t _EncodeAudio(const void* buffer,
|
status_t _EncodeAudio(const void* buffer,
|
||||||
int64 frameCount,
|
int64 frameCount,
|
||||||
media_encode_info* info);
|
media_encode_info* info);
|
||||||
@@ -55,12 +61,20 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
media_format fInputFormat;
|
media_format fInputFormat;
|
||||||
|
encode_parameters fEncodeParameters;
|
||||||
|
int fBitRateScale;
|
||||||
|
|
||||||
// FFmpeg related members
|
// FFmpeg related members
|
||||||
// TODO: Refactor common base class from AVCodec[De|En]Coder!
|
// TODO: Refactor common base class from AVCodec[De|En]Coder!
|
||||||
AVCodec* fCodec;
|
AVCodec* fCodec;
|
||||||
AVCodecContext* fContext;
|
AVCodecContext* fContext;
|
||||||
bool fCodecInitDone;
|
|
||||||
|
enum {
|
||||||
|
CODEC_INIT_NEEDED = 0,
|
||||||
|
CODEC_INIT_DONE,
|
||||||
|
CODEC_INIT_FAILED
|
||||||
|
};
|
||||||
|
uint32 fCodecInitStatus;
|
||||||
|
|
||||||
// For video (color space conversion):
|
// For video (color space conversion):
|
||||||
AVPicture fSrcFrame;
|
AVPicture fSrcFrame;
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ const EncoderDescription gEncoderTable[] = {
|
|||||||
},
|
},
|
||||||
B_ANY_FORMAT_FAMILY, // TODO: Hm, actually not really /any/ family...
|
B_ANY_FORMAT_FAMILY, // TODO: Hm, actually not really /any/ family...
|
||||||
B_MEDIA_RAW_VIDEO,
|
B_MEDIA_RAW_VIDEO,
|
||||||
B_MEDIA_ENCODED_VIDEO
|
B_MEDIA_ENCODED_VIDEO,
|
||||||
|
23
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -34,7 +35,8 @@ const EncoderDescription gEncoderTable[] = {
|
|||||||
},
|
},
|
||||||
B_MPEG_FORMAT_FAMILY,
|
B_MPEG_FORMAT_FAMILY,
|
||||||
B_MEDIA_RAW_VIDEO,
|
B_MEDIA_RAW_VIDEO,
|
||||||
B_MEDIA_ENCODED_VIDEO
|
B_MEDIA_ENCODED_VIDEO,
|
||||||
|
10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -46,7 +48,8 @@ const EncoderDescription gEncoderTable[] = {
|
|||||||
},
|
},
|
||||||
B_MPEG_FORMAT_FAMILY,
|
B_MPEG_FORMAT_FAMILY,
|
||||||
B_MEDIA_RAW_VIDEO,
|
B_MEDIA_RAW_VIDEO,
|
||||||
B_MEDIA_ENCODED_VIDEO
|
B_MEDIA_ENCODED_VIDEO,
|
||||||
|
15
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -58,7 +61,8 @@ const EncoderDescription gEncoderTable[] = {
|
|||||||
},
|
},
|
||||||
B_ANY_FORMAT_FAMILY,
|
B_ANY_FORMAT_FAMILY,
|
||||||
B_MEDIA_RAW_AUDIO,
|
B_MEDIA_RAW_AUDIO,
|
||||||
B_MEDIA_ENCODED_AUDIO
|
B_MEDIA_ENCODED_AUDIO,
|
||||||
|
1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -70,7 +74,8 @@ const EncoderDescription gEncoderTable[] = {
|
|||||||
},
|
},
|
||||||
B_ANY_FORMAT_FAMILY,
|
B_ANY_FORMAT_FAMILY,
|
||||||
B_MEDIA_RAW_AUDIO,
|
B_MEDIA_RAW_AUDIO,
|
||||||
B_MEDIA_ENCODED_AUDIO
|
B_MEDIA_ENCODED_AUDIO,
|
||||||
|
10
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ struct EncoderDescription {
|
|||||||
media_format_family format_family;
|
media_format_family format_family;
|
||||||
media_type input_type;
|
media_type input_type;
|
||||||
media_type output_type;
|
media_type output_type;
|
||||||
|
int bit_rate_scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,13 @@ FFmpegPlugin::GetSupportedFileFormats(const media_file_format** _fileFormats,
|
|||||||
Encoder*
|
Encoder*
|
||||||
FFmpegPlugin::NewEncoder(const media_codec_info& codecInfo)
|
FFmpegPlugin::NewEncoder(const media_codec_info& codecInfo)
|
||||||
{
|
{
|
||||||
return new(std::nothrow)AVCodecEncoder(codecInfo.sub_id);
|
for (size_t i = 0; i < gEncoderCount; i++) {
|
||||||
|
if (codecInfo.sub_id == gEncoderTable[i].codec_info.sub_id) {
|
||||||
|
return new(std::nothrow)AVCodecEncoder(codecInfo.sub_id,
|
||||||
|
gEncoderTable[i].bit_rate_scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,23 @@ const media_file_format gMuxerTable[] = {
|
|||||||
"mpg",
|
"mpg",
|
||||||
{ 0 }
|
{ 0 }
|
||||||
},
|
},
|
||||||
|
// TODO: This one rejects unknown codecs. We probably need to define
|
||||||
|
// a media_format_family for it so that Encoders can announce their support
|
||||||
|
// for it specifically.
|
||||||
|
// {
|
||||||
|
// media_file_format::B_WRITABLE
|
||||||
|
// | media_file_format::B_KNOWS_ENCODED_VIDEO
|
||||||
|
// | media_file_format::B_KNOWS_ENCODED_AUDIO,
|
||||||
|
// { 0 },
|
||||||
|
// B_AVI_FORMAT_FAMILY,
|
||||||
|
// 100,
|
||||||
|
// { 0 },
|
||||||
|
// "application/ogg",
|
||||||
|
// "Ogg (Xiph.Org Foundation)",
|
||||||
|
// "ogg",
|
||||||
|
// "ogg",
|
||||||
|
// { 0 }
|
||||||
|
// },
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t gMuxerCount = sizeof(gMuxerTable) / sizeof(media_file_format);
|
const size_t gMuxerCount = sizeof(gMuxerTable) / sizeof(media_file_format);
|
||||||
|
|||||||
@@ -686,7 +686,7 @@
|
|||||||
#define CONFIG_MXF_D10_MUXER 0
|
#define CONFIG_MXF_D10_MUXER 0
|
||||||
#define CONFIG_NULL_MUXER 0
|
#define CONFIG_NULL_MUXER 0
|
||||||
#define CONFIG_NUT_MUXER 0
|
#define CONFIG_NUT_MUXER 0
|
||||||
#define CONFIG_OGG_MUXER 0
|
#define CONFIG_OGG_MUXER 1
|
||||||
#define CONFIG_PCM_ALAW_MUXER 0
|
#define CONFIG_PCM_ALAW_MUXER 0
|
||||||
#define CONFIG_PCM_MULAW_MUXER 0
|
#define CONFIG_PCM_MULAW_MUXER 0
|
||||||
#define CONFIG_PCM_F64BE_MUXER 0
|
#define CONFIG_PCM_F64BE_MUXER 0
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ Encoder::~Encoder()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Convenience stubs
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Encoder::AddTrackInfo(uint32 code, const void* data, size_t size, uint32 flags)
|
Encoder::AddTrackInfo(uint32 code, const void* data, size_t size, uint32 flags)
|
||||||
{
|
{
|
||||||
@@ -33,6 +36,34 @@ Encoder::AddTrackInfo(uint32 code, const void* data, size_t size, uint32 flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BView*
|
||||||
|
Encoder::ParameterView()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BParameterWeb*
|
||||||
|
Encoder::ParameterWeb()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Encoder::GetParameterValue(int32 id, void* value, size_t* size) const
|
||||||
|
{
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Encoder::SetParameterValue(int32 id, const void* value, size_t size)
|
||||||
|
{
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Encoder::GetEncodeParameters(encode_parameters* parameters) const
|
Encoder::GetEncodeParameters(encode_parameters* parameters) const
|
||||||
{
|
{
|
||||||
@@ -41,12 +72,15 @@ Encoder::GetEncodeParameters(encode_parameters* parameters) const
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Encoder::SetEncodeParameters(encode_parameters* parameters) const
|
Encoder::SetEncodeParameters(encode_parameters* parameters)
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
return B_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Encoder::WriteChunk(const void* chunkBuffer, size_t chunkSize,
|
Encoder::WriteChunk(const void* chunkBuffer, size_t chunkSize,
|
||||||
media_encode_info* encodeInfo)
|
media_encode_info* encodeInfo)
|
||||||
@@ -63,6 +97,9 @@ Encoder::SetChunkWriter(ChunkWriter* writer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - FBC padding
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Encoder::Perform(perform_code code, void* data)
|
Encoder::Perform(perform_code code, void* data)
|
||||||
{
|
{
|
||||||
@@ -75,9 +112,24 @@ void Encoder::_ReservedEncoder2() {}
|
|||||||
void Encoder::_ReservedEncoder3() {}
|
void Encoder::_ReservedEncoder3() {}
|
||||||
void Encoder::_ReservedEncoder4() {}
|
void Encoder::_ReservedEncoder4() {}
|
||||||
void Encoder::_ReservedEncoder5() {}
|
void Encoder::_ReservedEncoder5() {}
|
||||||
|
void Encoder::_ReservedEncoder6() {}
|
||||||
|
void Encoder::_ReservedEncoder7() {}
|
||||||
|
void Encoder::_ReservedEncoder8() {}
|
||||||
|
void Encoder::_ReservedEncoder9() {}
|
||||||
|
void Encoder::_ReservedEncoder10() {}
|
||||||
|
void Encoder::_ReservedEncoder11() {}
|
||||||
|
void Encoder::_ReservedEncoder12() {}
|
||||||
|
void Encoder::_ReservedEncoder13() {}
|
||||||
|
void Encoder::_ReservedEncoder14() {}
|
||||||
|
void Encoder::_ReservedEncoder15() {}
|
||||||
|
void Encoder::_ReservedEncoder16() {}
|
||||||
|
void Encoder::_ReservedEncoder17() {}
|
||||||
|
void Encoder::_ReservedEncoder18() {}
|
||||||
|
void Encoder::_ReservedEncoder19() {}
|
||||||
|
void Encoder::_ReservedEncoder20() {}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark - EncoderPlugin
|
||||||
|
|
||||||
|
|
||||||
EncoderPlugin::EncoderPlugin()
|
EncoderPlugin::EncoderPlugin()
|
||||||
|
|||||||
+114
-69
@@ -76,6 +76,7 @@ BMediaTrack::~BMediaTrack()
|
|||||||
CALLED();
|
CALLED();
|
||||||
_plugin_manager.DestroyDecoder(fRawDecoder);
|
_plugin_manager.DestroyDecoder(fRawDecoder);
|
||||||
_plugin_manager.DestroyDecoder(fDecoder);
|
_plugin_manager.DestroyDecoder(fDecoder);
|
||||||
|
_plugin_manager.DestroyDecoder(fEncoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
@@ -321,28 +322,31 @@ BMediaTrack::ReadFrames(void *out_buffer,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMediaTrack::ReplaceFrames(const void *in_buffer,
|
BMediaTrack::ReplaceFrames(const void* inBuffer, int64* inOutFrameCount,
|
||||||
int64 *io_frameCount,
|
const media_header* mediaHeader)
|
||||||
const media_header *mh)
|
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
|
|
||||||
return B_OK;
|
// TODO: Actually, a file is either open for reading or writing at the
|
||||||
|
// moment. Since the chunk size of encoded media data will change,
|
||||||
|
// implementing this call will only be possible for raw media tracks.
|
||||||
|
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMediaTrack::SeekToTime(bigtime_t *inout_time, int32 flags)
|
BMediaTrack::SeekToTime(bigtime_t* inOutTime, int32 flags)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
if (!fDecoder || !fExtractor)
|
if (!fDecoder || !fExtractor)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
if (!inout_time)
|
if (!inOutTime)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK)
|
uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK)
|
||||||
| B_MEDIA_SEEK_TO_TIME;
|
| B_MEDIA_SEEK_TO_TIME;
|
||||||
bigtime_t seekTime = *inout_time;
|
bigtime_t seekTime = *inOutTime;
|
||||||
|
|
||||||
int64 frame = 0;
|
int64 frame = 0;
|
||||||
bigtime_t time = seekTime;
|
bigtime_t time = seekTime;
|
||||||
@@ -355,7 +359,7 @@ BMediaTrack::SeekToTime(bigtime_t *inout_time, int32 flags)
|
|||||||
// TODO: Codecs cannot actually "seek" in the stream, all they
|
// TODO: Codecs cannot actually "seek" in the stream, all they
|
||||||
// can do is "reset" their decoder state, since they are made
|
// can do is "reset" their decoder state, since they are made
|
||||||
// aware of the fact that there will be a jump in the data. Maybe
|
// aware of the fact that there will be a jump in the data. Maybe
|
||||||
// rename the codec method?
|
// rename the Decoder method?
|
||||||
result = fDecoder->Seek(seekTo, 0, &frame, seekTime, &time);
|
result = fDecoder->Seek(seekTo, 0, &frame, seekTime, &time);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
ERROR("BMediaTrack::SeekToTime: decoder seek failed\n");
|
ERROR("BMediaTrack::SeekToTime: decoder seek failed\n");
|
||||||
@@ -370,11 +374,12 @@ BMediaTrack::SeekToTime(bigtime_t *inout_time, int32 flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*inout_time = time;
|
*inOutTime = time;
|
||||||
fCurFrame = frame;
|
fCurFrame = frame;
|
||||||
fCurTime = time;
|
fCurTime = time;
|
||||||
|
|
||||||
PRINT(1, "BMediaTrack::SeekToTime finished, requested %.6f, result %.6f\n", seekTime / 1000000.0, *inout_time / 1000000.0);
|
PRINT(1, "BMediaTrack::SeekToTime finished, requested %.6f, result %.6f\n",
|
||||||
|
seekTime / 1000000.0, *inOutTime / 1000000.0);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -589,102 +594,142 @@ BMediaTrack::Flush()
|
|||||||
BParameterWeb*
|
BParameterWeb*
|
||||||
BMediaTrack::Web()
|
BMediaTrack::Web()
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED();
|
BParameterWeb* web;
|
||||||
|
if (GetParameterWeb(&web) == B_OK)
|
||||||
|
return web;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// returns a copy of the parameter web
|
|
||||||
status_t
|
status_t
|
||||||
BMediaTrack::GetParameterWeb(BParameterWeb** outWeb)
|
BMediaTrack::GetParameterWeb(BParameterWeb** outWeb)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED();
|
if (outWeb == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (fEncoder == NULL)
|
||||||
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
// TODO: This method is new in Haiku. The header mentions it returns a
|
||||||
|
// copy. But how could it even do that? How can one clone a web and make
|
||||||
|
// it point to the same BControllable?
|
||||||
|
*outWeb = fEncoder->ParameterWeb();
|
||||||
|
if (*outWeb != NULL)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMediaTrack::GetParameterValue(int32 id, void* value, size_t* size)
|
||||||
|
{
|
||||||
|
if (value == NULL || size == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (fEncoder == NULL)
|
||||||
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
return fEncoder->GetParameterValue(id, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMediaTrack::SetParameterValue(int32 id, const void* value, size_t size)
|
||||||
|
{
|
||||||
|
if (value == NULL || size == 0)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (fEncoder == NULL)
|
||||||
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
return fEncoder->SetParameterValue(id, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BView*
|
||||||
|
BMediaTrack::GetParameterView()
|
||||||
|
{
|
||||||
|
if (fEncoder == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return fEncoder->ParameterView();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMediaTrack::GetQuality(float* quality)
|
||||||
|
{
|
||||||
|
if (quality == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
encode_parameters parameters;
|
||||||
|
status_t ret = GetEncodeParameters(¶meters);
|
||||||
|
if (ret != B_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*quality = parameters.quality;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMediaTrack::GetParameterValue(int32 id,
|
|
||||||
void *valu,
|
|
||||||
size_t *size)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMediaTrack::SetParameterValue(int32 id,
|
|
||||||
const void *valu,
|
|
||||||
size_t size)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BView *
|
|
||||||
BMediaTrack::GetParameterView()
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMediaTrack::GetQuality(float *quality)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMediaTrack::SetQuality(float quality)
|
BMediaTrack::SetQuality(float quality)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED();
|
encode_parameters parameters;
|
||||||
|
status_t ret = GetEncodeParameters(¶meters);
|
||||||
|
if (ret != B_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
return B_ERROR;
|
if (quality < 0.0f)
|
||||||
|
quality = 0.0f;
|
||||||
|
if (quality > 1.0f)
|
||||||
|
quality = 1.0f;
|
||||||
|
|
||||||
|
parameters.quality = quality;
|
||||||
|
|
||||||
|
return SetEncodeParameters(¶meters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMediaTrack::GetEncodeParameters(encode_parameters *parameters) const
|
BMediaTrack::GetEncodeParameters(encode_parameters* parameters) const
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED();
|
if (parameters == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
return B_ERROR;
|
if (fEncoder == NULL)
|
||||||
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
return fEncoder->GetEncodeParameters(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMediaTrack::SetEncodeParameters(encode_parameters *parameters)
|
BMediaTrack::SetEncodeParameters(encode_parameters *parameters)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED();
|
if (parameters == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
return B_ERROR;
|
if (fEncoder == NULL)
|
||||||
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
return fEncoder->SetEncodeParameters(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMediaTrack::Perform(int32 selector,
|
BMediaTrack::Perform(int32 selector, void* data)
|
||||||
void *data)
|
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED();
|
return B_OK;
|
||||||
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************
|
// #pragma mark - private
|
||||||
* private BMediaTrack
|
|
||||||
*************************************************************/
|
|
||||||
|
|
||||||
BMediaTrack::BMediaTrack(BPrivate::media::MediaExtractor *extractor,
|
|
||||||
int32 stream)
|
BMediaTrack::BMediaTrack(BPrivate::media::MediaExtractor* extractor,
|
||||||
|
int32 stream)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
fWorkaroundFlags = 0;
|
fWorkaroundFlags = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user