new MediaFormats. node monitoring codec plugin loading. codec mods to support new codec api to retrieve supported formats.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6465 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
5b25332a79
commit
fa8dbc019d
@ -71,6 +71,9 @@ enum {
|
||||
MEDIA_SERVER_SEND_NOTIFICATIONS,
|
||||
|
||||
MEDIA_SERVER_GET_FORMATS,
|
||||
MEDIA_SERVER_MAKE_FORMAT_FOR,
|
||||
|
||||
MEDIA_SERVER_READY,
|
||||
};
|
||||
|
||||
// Raw port based communication
|
||||
|
@ -49,8 +49,8 @@ class DecoderPlugin : public virtual MediaPlugin
|
||||
public:
|
||||
DecoderPlugin();
|
||||
|
||||
virtual Decoder *NewDecoder() = 0;
|
||||
virtual status_t RegisterDecoder() = 0;
|
||||
virtual Decoder *NewDecoder(uint index) = 0;
|
||||
virtual status_t GetSupportedFormats(media_format ** formats, size_t * count) = 0;
|
||||
};
|
||||
|
||||
} } // namespace BPrivate::media
|
||||
|
@ -1,4 +1,694 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: avCodec.cpp
|
||||
/
|
||||
/ Description: FFMpeg Generic Decoder for BeOS Release 5.
|
||||
/
|
||||
/ Disclaimer: This decoder is based on undocumented APIs.
|
||||
/ Therefore it is likely, if not certain, to break in future
|
||||
/ versions of BeOS. This piece of software is in no way
|
||||
/ connected to or even supported by Be, Inc.
|
||||
/
|
||||
/ Copyright (C) 2001 François Revol. All Rights Reserved.
|
||||
/ Some code from MPEG I Decoder from Carlos Hasan.
|
||||
/ Had some help from Axeld
|
||||
/
|
||||
******************************************************************************/
|
||||
|
||||
void foo()
|
||||
#include <Debug.h>
|
||||
#include <OS.h>
|
||||
#include <Bitmap.h>
|
||||
#include <string.h>
|
||||
#include "avcodec.h"
|
||||
|
||||
struct wave_format_ex
|
||||
{
|
||||
uint16 format_tag;
|
||||
uint16 channels;
|
||||
uint32 frames_per_sec;
|
||||
uint32 avg_bytes_per_sec;
|
||||
uint16 block_align;
|
||||
uint16 bits_per_sample;
|
||||
uint16 extra_size;
|
||||
// extra_data[extra_size]
|
||||
} _PACKED;
|
||||
|
||||
/* uncommenting will make Decode() set the current thread priority to time sharing, so it won't totally freeze
|
||||
* if you busy-loop in there (to help debug with CD Manager
|
||||
*/
|
||||
//#define UNREAL
|
||||
|
||||
#define CLOSE_ON_RESET
|
||||
|
||||
const char *media_type_name(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case B_MEDIA_NO_TYPE:
|
||||
return "B_MEDIA_NO_TYPE";
|
||||
case B_MEDIA_RAW_AUDIO:
|
||||
return "B_MEDIA_RAW_AUDIO";
|
||||
case B_MEDIA_RAW_VIDEO:
|
||||
return "B_MEDIA_RAW_VIDEO";
|
||||
case B_MEDIA_VBL:
|
||||
return "B_MEDIA_VBL";
|
||||
case B_MEDIA_TIMECODE:
|
||||
return "B_MEDIA_TIMECODE";
|
||||
case B_MEDIA_MIDI:
|
||||
return "B_MEDIA_MIDI";
|
||||
case B_MEDIA_TEXT:
|
||||
return "B_MEDIA_TEXT";
|
||||
case B_MEDIA_HTML:
|
||||
return "B_MEDIA_HTML";
|
||||
case B_MEDIA_MULTISTREAM:
|
||||
return "B_MEDIA_MULTISTREAM";
|
||||
case B_MEDIA_PARAMETERS:
|
||||
return "B_MEDIA_PARAMETERS";
|
||||
case B_MEDIA_ENCODED_AUDIO:
|
||||
return "B_MEDIA_ENCODED_AUDIO";
|
||||
case B_MEDIA_ENCODED_VIDEO:
|
||||
return "B_MEDIA_ENCODED_VIDEO";
|
||||
case B_MEDIA_UNKNOWN_TYPE:
|
||||
default:
|
||||
return "B_MEDIA_UNKNOWN_TYPE";
|
||||
}
|
||||
}
|
||||
|
||||
char make_printable_char(uchar c)
|
||||
{
|
||||
// c &= 0x7F;
|
||||
if (c >= 0x20 && c < 0x7F)
|
||||
return c;
|
||||
return '.';
|
||||
}
|
||||
|
||||
void print_hex(unsigned char *buff, int len)
|
||||
{
|
||||
int i, j;
|
||||
for(i=0; i<len+7;i+=8) {
|
||||
for (j=0; j<8; j++) {
|
||||
if (i+j < len)
|
||||
printf("%02X", buff[i+j]);
|
||||
else
|
||||
printf(" ");
|
||||
if (j==3)
|
||||
printf(" ");
|
||||
}
|
||||
printf("\t");
|
||||
for (j=0; j<8; j++) {
|
||||
if (i+j < len)
|
||||
printf("%c", make_printable_char(buff[i+j]));
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void print_media_header(media_header *mh)
|
||||
{
|
||||
printf("media_header {%s, size_used: %ld, start_time: %lld (%02d:%02d.%02d), field_sequence=%lu, user_data_type: .4s, file_pos: %ld, orig_size: %ld, data_offset: %ld}\n",
|
||||
media_type_name(mh->type), mh->size_used, mh->start_time,
|
||||
int((mh->start_time / 60000000) % 60),
|
||||
int((mh->start_time / 1000000) % 60),
|
||||
int((mh->start_time / 10000) % 100),
|
||||
(long)mh->u.raw_video.field_sequence,
|
||||
//&(mh->user_data_type),
|
||||
(long)mh->file_pos,
|
||||
(long)mh->orig_size,
|
||||
mh->data_offset);
|
||||
}
|
||||
|
||||
void print_media_decode_info(media_decode_info *info)
|
||||
{
|
||||
if (info)
|
||||
printf("media_decode_info {time_to_decode: %lld, file_format_data_size: %ld, codec_data_size: %ld}\n", info->time_to_decode, info->file_format_data_size, info->codec_data_size);
|
||||
else
|
||||
printf("media_decode_info (null)\n");
|
||||
}
|
||||
|
||||
avCodec::avCodec()
|
||||
: fHeader(),
|
||||
fInfo(),
|
||||
fInputFormat(),
|
||||
fOutputVideoFormat(),
|
||||
fOutputAudioFormat(),
|
||||
fFrame(0),
|
||||
isAudio(false),
|
||||
fData(NULL),
|
||||
fOffset(0L),
|
||||
fSize(0L),
|
||||
fCodec(NULL),
|
||||
ffc(NULL),
|
||||
fCodecInitDone(false),
|
||||
conv_func(NULL),
|
||||
fExtraData(NULL),
|
||||
fExtraDataSize(0),
|
||||
fBlockAlign(0),
|
||||
fOutputBuffer(0)
|
||||
{
|
||||
PRINT(("[%c] avCodec::avCodec()\n", isAudio?('a'):('v')));
|
||||
|
||||
|
||||
static volatile vint32 ff_init_count = 0;
|
||||
static bool ff_init_done = false;
|
||||
PRINT(("avCodec::register_decoder()\n"));
|
||||
|
||||
// prevent multiple inits
|
||||
if (atomic_add(&ff_init_count, 1) > 1) {
|
||||
puts("NOT first init !");
|
||||
atomic_add(&ff_init_count, -1);
|
||||
// spin until the thread that is initing is done
|
||||
while (!ff_init_done)
|
||||
snooze(20000);
|
||||
} else {
|
||||
puts("first init !");
|
||||
avcodec_init();
|
||||
avcodec_register_all();
|
||||
ff_init_done = true;
|
||||
}
|
||||
|
||||
// memset(&opicture, 0, sizeof(AVPicture));
|
||||
ffc = avcodec_alloc_context();
|
||||
ffpicture = avcodec_alloc_frame();
|
||||
// ffpicture->type = FF_BUFFER_TYPE_USER;
|
||||
opicture = avcodec_alloc_frame();
|
||||
}
|
||||
|
||||
|
||||
avCodec::~avCodec()
|
||||
{
|
||||
PRINT(("[%c] avCodec::~avCodec()\n", isAudio?('a'):('v')));
|
||||
|
||||
if(fCodecInitDone)
|
||||
avcodec_close(ffc);
|
||||
|
||||
free(opicture);
|
||||
free(ffpicture);
|
||||
free(ffc);
|
||||
|
||||
delete [] fExtraData;
|
||||
delete [] fOutputBuffer;
|
||||
}
|
||||
|
||||
|
||||
void avCodec::GetCodecInfo(media_codec_info *mci)
|
||||
{
|
||||
sprintf(mci->short_name, "ff:%s", fCodec->name);
|
||||
sprintf(mci->pretty_name, "%s (libavcodec %s)", gCodecTable[ffcodec_index_in_table].prettyname, fCodec->name);
|
||||
}
|
||||
|
||||
|
||||
status_t avCodec::Setup(media_format *input_format, const void *in_info, int32 in_size)
|
||||
{
|
||||
if (input_format->type != B_MEDIA_ENCODED_AUDIO && input_format->type != B_MEDIA_ENCODED_VIDEO)
|
||||
return B_ERROR;
|
||||
|
||||
isAudio = (input_format->type == B_MEDIA_ENCODED_AUDIO);
|
||||
|
||||
if (isAudio)
|
||||
fOutputBuffer = new char[100000];
|
||||
|
||||
#if DEBUG
|
||||
char buffer[1024];
|
||||
string_for_format(*input_format, buffer, sizeof(buffer));
|
||||
PRINT(("[%c] input_format=%s\n", isAudio?('a'):('v'), buffer));
|
||||
PRINT(("[%c] in_info_size=%ld\n", isAudio?('a'):('v'), in_size));
|
||||
print_hex((uchar *)in_info, in_size);
|
||||
PRINT(("[%c] user_data_type=%08lx\n", isAudio?('a'):('v'), input_format->user_data_type));
|
||||
print_hex((uchar *)input_format->user_data, 48);
|
||||
// PRINT(("[%c] meta_data_size=%ld\n", isAudio?('a'):('v'), input_format->meta_data_size));
|
||||
#else
|
||||
(void)(in_info);
|
||||
(void)(in_size);
|
||||
#endif
|
||||
|
||||
media_format_description descr;
|
||||
for (int32 i = 0; gCodecTable[i].id; i++)
|
||||
{
|
||||
ffcodec_index_in_table = i;
|
||||
uint32 cid;
|
||||
|
||||
if(BMediaFormats().GetCodeFor(*input_format,gCodecTable[i].family,&descr) == B_OK
|
||||
&& gCodecTable[i].type == input_format->type)
|
||||
{
|
||||
PRINT((" codec id = \"%c%c%c%c\"\n", (descr.u.avi.codec >> 24) & 0xff,
|
||||
(descr.u.avi.codec >> 16) & 0xff,
|
||||
(descr.u.avi.codec >> 8) & 0xff,
|
||||
descr.u.avi.codec & 0xff));
|
||||
switch(gCodecTable[i].family) {
|
||||
case B_WAV_FORMAT_FAMILY:
|
||||
cid = descr.u.wav.codec;
|
||||
break;
|
||||
case B_AVI_FORMAT_FAMILY:
|
||||
cid = descr.u.avi.codec;
|
||||
break;
|
||||
case B_MPEG_FORMAT_FAMILY:
|
||||
cid = descr.u.mpeg.id;
|
||||
break;
|
||||
case B_QUICKTIME_FORMAT_FAMILY:
|
||||
cid = descr.u.quicktime.codec;
|
||||
break;
|
||||
default:
|
||||
puts("ERR family");
|
||||
return B_ERROR;
|
||||
}
|
||||
if (gCodecTable[i].family == descr.family && gCodecTable[i].fourcc == cid) {
|
||||
fCodec = avcodec_find_decoder(gCodecTable[i].id);
|
||||
if (!fCodec) {
|
||||
printf("avCodec: unable to find the correct ffmpeg decoder (id = %d)!!!\n",gCodecTable[i].id);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// ffc->codec_id = gCodecTable[i].id;
|
||||
|
||||
if (gCodecTable[i].family == B_WAV_FORMAT_FAMILY) {
|
||||
const wave_format_ex *wfmt_data = (const wave_format_ex *)input_format->MetaData();
|
||||
int wfmt_size = input_format->MetaDataSize();
|
||||
if (wfmt_data && wfmt_size) {
|
||||
fBlockAlign = wfmt_data->block_align;
|
||||
fExtraDataSize = wfmt_data->extra_size;
|
||||
printf("############# fExtraDataSize %d\n", fExtraDataSize);
|
||||
printf("############# fBlockAlign %d\n", fBlockAlign);
|
||||
printf("############# wfmt_size %d\n", wfmt_size);
|
||||
printf("############# wave_format_ex %ld\n", sizeof(wave_format_ex));
|
||||
if (fExtraDataSize) {
|
||||
fExtraData = new char [fExtraDataSize];
|
||||
memcpy(fExtraData, wfmt_data + 1, fExtraDataSize);
|
||||
|
||||
uint8 *p = (uint8 *)fExtraData;
|
||||
printf("extra_data: %d: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
fExtraDataSize, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
|
||||
}
|
||||
// static const unsigned char wma_extradata[6] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00 };
|
||||
// fExtraData = (void *)wma_extradata;
|
||||
// fExtraDataSize = 6;
|
||||
}
|
||||
}
|
||||
|
||||
fInputFormat = *input_format;
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("avCodec::Setup failed!\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t avCodec::Seek(uint32 in_towhat,int64 in_requiredFrame, int64 *inout_frame,
|
||||
bigtime_t in_requiredTime, bigtime_t *inout_time)
|
||||
{
|
||||
|
||||
// reset the ffmpeg codec
|
||||
// to flush buffers, so we keep the sync
|
||||
|
||||
#ifdef CLOSE_ON_RESET
|
||||
|
||||
if (isAudio && fCodecInitDone)
|
||||
{
|
||||
fCodecInitDone = false;
|
||||
avcodec_close(ffc);
|
||||
fCodecInitDone = (avcodec_open(ffc, fCodec) >= 0);
|
||||
fData = NULL;
|
||||
fSize = 0LL;
|
||||
fOffset = 0;
|
||||
}
|
||||
|
||||
#endif /* CLOSE_ON_RESET */
|
||||
|
||||
fFrame = *inout_frame;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t avCodec::NegotiateOutputFormat(media_format *inout_format)
|
||||
{
|
||||
// int ffPixelFmt;
|
||||
enum PixelFormat ffPixelFmt;
|
||||
|
||||
PRINT(("[%c] avCodec::Format()\n", isAudio?('a'):('v')));
|
||||
|
||||
#if DEBUG
|
||||
char buffer[1024];
|
||||
string_for_format(*inout_format, buffer, sizeof(buffer));
|
||||
PRINT(("[%c] in_format=%s\n", isAudio?('a'):('v'), buffer));
|
||||
#endif
|
||||
|
||||
// close any previous instance
|
||||
if (fCodecInitDone) {
|
||||
fCodecInitDone = false;
|
||||
avcodec_close(ffc);
|
||||
}
|
||||
|
||||
if (isAudio) {
|
||||
fOutputAudioFormat = media_raw_audio_format::wildcard;
|
||||
fOutputAudioFormat.format = media_raw_audio_format::B_AUDIO_SHORT;
|
||||
fOutputAudioFormat.byte_order = B_MEDIA_HOST_ENDIAN;
|
||||
fOutputAudioFormat.frame_rate = fInputFormat.u.encoded_audio.output.frame_rate;
|
||||
fOutputAudioFormat.channel_count = fInputFormat.u.encoded_audio.output.channel_count;
|
||||
fOutputAudioFormat.buffer_size = 1024 * fInputFormat.u.encoded_audio.output.channel_count;
|
||||
inout_format->type = B_MEDIA_RAW_AUDIO;
|
||||
inout_format->u.raw_audio = fOutputAudioFormat;
|
||||
|
||||
ffc->bit_rate = (int) fInputFormat.u.encoded_audio.bit_rate;
|
||||
ffc->sample_rate = (int) fInputFormat.u.encoded_audio.output.frame_rate;
|
||||
ffc->channels = fInputFormat.u.encoded_audio.output.channel_count;
|
||||
|
||||
ffc->block_align = fBlockAlign;
|
||||
ffc->extradata = fExtraData;
|
||||
ffc->extradata_size = fExtraDataSize;
|
||||
|
||||
if (avcodec_open(ffc, fCodec) >= 0)
|
||||
fCodecInitDone = true;
|
||||
|
||||
if (ffc->codec_id == CODEC_ID_WMAV1) {
|
||||
printf("########################### WMA1\n");
|
||||
}
|
||||
if (ffc->codec_id == CODEC_ID_WMAV2) {
|
||||
printf("########################### WMA2\n");
|
||||
}
|
||||
if (ffc->codec_id == CODEC_ID_MP2) {
|
||||
printf("########################### MP3\n");
|
||||
}
|
||||
|
||||
PRINT(("audio: bit_rate = %d, sample_rate = %d, chans = %d\n", ffc->bit_rate, ffc->sample_rate, ffc->channels));
|
||||
|
||||
fStartTime = 0;
|
||||
fOutputFrameCount = fOutputAudioFormat.buffer_size / (2 * fOutputAudioFormat.channel_count);
|
||||
fOutputFrameRate = fOutputAudioFormat.frame_rate;
|
||||
fChunkBuffer = 0;
|
||||
fChunkBufferOffset = 0;
|
||||
fChunkBufferSize = 0;
|
||||
fOutputBufferOffset = 0;
|
||||
fOutputBufferSize = 0;
|
||||
|
||||
} else { // no AUDIO_CODEC
|
||||
|
||||
fOutputVideoFormat = fInputFormat.u.encoded_video.output;
|
||||
|
||||
ffc->width = fOutputVideoFormat.display.line_width;
|
||||
ffc->height = fOutputVideoFormat.display.line_count;
|
||||
ffc->frame_rate = (int)(fOutputVideoFormat.field_rate * ffc->frame_rate_base);
|
||||
|
||||
// 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 default
|
||||
// colordepth is RGB32)
|
||||
if (inout_format->u.raw_video.display.format == B_YCbCr422)
|
||||
fOutputVideoFormat.display.format = B_YCbCr422;
|
||||
else
|
||||
fOutputVideoFormat.display.format = B_RGB32;
|
||||
|
||||
// search for a pixel-format the codec handles
|
||||
while (!fCodecInitDone)
|
||||
{
|
||||
// find the proper ff pixel format and the convertion func
|
||||
conv_func = resolve_colorspace(fOutputVideoFormat.display.format, &ffPixelFmt);
|
||||
PRINT(("ffc = %08lx, fCodec = %08lx, conv_func = %08lx\n", ffc, fCodec, conv_func));
|
||||
if (!conv_func)
|
||||
{
|
||||
PRINT(("no conv_func (1) !\n"));
|
||||
// return B_ERROR;
|
||||
}
|
||||
// ffc->pix_fmt = ffPixelFmt = 0; // DEBUG !!!
|
||||
// ffc->pix_fmt =
|
||||
// ffPixelFmt = PIX_FMT_YUV420P; // DEBUG !!!
|
||||
// ffc->pix_fmt = ffPixelFmt = PIX_FMT_YUV420P; // DEBUG !!!
|
||||
if (avcodec_open(ffc, fCodec) >= 0)
|
||||
fCodecInitDone = true;
|
||||
else
|
||||
printf("avCodec: error in avcodec_open()\n");
|
||||
|
||||
conv_func = resolve_colorspace(fOutputVideoFormat.display.format, &ffc->pix_fmt);
|
||||
PRINT(("ffc = %08lx, fCodec = %08lx, conv_func = %08lx, ffcolspace= %s\n", ffc, fCodec, conv_func, pixfmt_to_string(ffc->pix_fmt)));
|
||||
if (!conv_func)
|
||||
{
|
||||
PRINT(("no conv_func (2) !\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
PRINT(("PIXFMT: %s -> %s\n", pixfmt_to_string(ffPixelFmt), pixfmt_to_string(ffc->pix_fmt)));
|
||||
}
|
||||
|
||||
if (fOutputVideoFormat.display.format == B_YCbCr422)
|
||||
fOutputVideoFormat.display.bytes_per_row = 2 * fOutputVideoFormat.display.line_width;
|
||||
else
|
||||
fOutputVideoFormat.display.bytes_per_row = 4 * fOutputVideoFormat.display.line_width;
|
||||
|
||||
inout_format->type = B_MEDIA_RAW_VIDEO;
|
||||
inout_format->u.raw_video = fOutputVideoFormat;
|
||||
|
||||
}
|
||||
|
||||
inout_format->require_flags = 0;
|
||||
inout_format->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
|
||||
|
||||
#if DEBUG
|
||||
string_for_format(*inout_format, buffer, sizeof(buffer));
|
||||
PRINT(("[%c] out_format=%s\n", isAudio?('a'):('v'), buffer));
|
||||
#endif
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t avCodec::Decode(void *out_buffer, int64 *out_frameCount, media_header *mh,
|
||||
media_decode_info *info)
|
||||
{
|
||||
if (out_buffer == NULL || out_frameCount == NULL || mh == NULL || !fCodecInitDone)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
int len = 0;
|
||||
int got_picture = 0;
|
||||
|
||||
#ifdef DO_PROFILING
|
||||
bigtime_t prof_t1, prof_t2, prof_t3;
|
||||
static bigtime_t diff1 = 0, diff2 = 0;
|
||||
static long prof_cnt = 0;
|
||||
#endif
|
||||
|
||||
#ifdef UNREAL
|
||||
set_thread_priority(find_thread(NULL), B_NORMAL_PRIORITY);
|
||||
#endif
|
||||
|
||||
PRINT(("[%c] avCodec::Decode()\n", isAudio?('a'):('v')));
|
||||
|
||||
#if DEBUG
|
||||
// asm("int $0x0");
|
||||
#endif
|
||||
|
||||
if (isAudio) {
|
||||
|
||||
mh->start_time = fStartTime;
|
||||
|
||||
printf("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) {
|
||||
printf("############ fOutputBufferSize %ld\n", fOutputBufferSize);
|
||||
fOutputBufferSize = 0;
|
||||
}
|
||||
if (fChunkBufferSize < 0) {
|
||||
printf("############ fChunkBufferSize %ld\n", fChunkBufferSize);
|
||||
fChunkBufferSize = 0;
|
||||
}
|
||||
|
||||
if (fOutputBufferSize > 0) {
|
||||
int32 frames = min_c(fOutputFrameCount - *out_frameCount, fOutputBufferSize / 4);
|
||||
memcpy(output_buffer, fOutputBuffer + fOutputBufferOffset, frames * 4);
|
||||
fOutputBufferOffset += frames * 4;
|
||||
fOutputBufferSize -= frames * 4;
|
||||
output_buffer += frames * 4;
|
||||
*out_frameCount += frames;
|
||||
fStartTime += (bigtime_t)((1000000LL * frames) / fOutputFrameRate);
|
||||
continue;
|
||||
}
|
||||
if (fChunkBufferSize == 0) {
|
||||
media_header mh;
|
||||
status_t err;
|
||||
err = GetNextChunk((void **)&fChunkBuffer, &fChunkBufferSize, &mh);
|
||||
if (err != B_OK || fChunkBufferSize < 0) {
|
||||
printf("GetNextChunk error\n");
|
||||
fChunkBufferSize = 0;
|
||||
break;
|
||||
}
|
||||
fChunkBufferOffset = 0;
|
||||
fStartTime = mh.start_time;
|
||||
continue;
|
||||
}
|
||||
if (fOutputBufferSize == 0) {
|
||||
int len, out_size;
|
||||
len = avcodec_decode_audio(ffc, (short *)fOutputBuffer, &out_size, (uint8_t *)fChunkBuffer + fChunkBufferOffset, fChunkBufferSize);
|
||||
if (len < 0) {
|
||||
printf("########### audio decode error, fChunkBufferSize %ld, fChunkBufferOffset %ld\n", fChunkBufferSize, fChunkBufferOffset);
|
||||
out_size = 0;
|
||||
len = 0;
|
||||
fChunkBufferOffset = 0;
|
||||
fChunkBufferSize = 0;
|
||||
} else
|
||||
printf("audio decode: len %d, out_size %d\n", len, out_size);
|
||||
fChunkBufferOffset += len;
|
||||
fChunkBufferSize -= len;
|
||||
fOutputBufferOffset = 0;
|
||||
fOutputBufferSize = out_size;
|
||||
}
|
||||
}
|
||||
|
||||
} else { // no AUDIO_CODEC
|
||||
// VIDEO
|
||||
status_t err;
|
||||
|
||||
#ifdef DEBUG
|
||||
//print_media_header(mh);
|
||||
//print_media_decode_info(info);
|
||||
#endif
|
||||
mh->type = B_MEDIA_RAW_VIDEO;
|
||||
// mh->start_time = (bigtime_t) (1000000.0 * fFrame / fOutputVideoFormat.field_rate);
|
||||
mh->start_time = fHeader.start_time;
|
||||
mh->file_pos = mh->orig_size = 0;
|
||||
mh->u.raw_video.field_gamma = 1.0;
|
||||
mh->u.raw_video.field_sequence = fFrame;
|
||||
mh->u.raw_video.field_number = 0;
|
||||
mh->u.raw_video.pulldown_number = 0;
|
||||
mh->u.raw_video.first_active_line = 1;
|
||||
mh->u.raw_video.line_count = fOutputVideoFormat.display.line_count;
|
||||
/**/
|
||||
PRINT(("[%c] start_time=%02d:%02d.%02d field_sequence=%u\n",
|
||||
isAudio?('a'):('v'),
|
||||
int((mh->start_time / 60000000) % 60),
|
||||
int((mh->start_time / 1000000) % 60),
|
||||
int((mh->start_time / 10000) % 100),
|
||||
mh->u.raw_video.field_sequence));
|
||||
/**/
|
||||
fSize = 0L;
|
||||
err = GetNextChunk(&fData, &fSize, &fHeader);
|
||||
if (err != B_OK) {
|
||||
PRINT(("avCodec::Decode(): error 0x%08lx from GetNextChunk()\n", err));
|
||||
return B_ERROR;
|
||||
}
|
||||
PRINT(("avCodec::Decode(): passed GetNextChunk(), fSize=%ld\n", fSize));
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
puts("Chunk:");
|
||||
for(i=0; i<2;i+=8) {
|
||||
char *buff = (char *)fData;
|
||||
printf("%08lX %08lX\t", *(long *)&buff[i], *(long *)&buff[i+4]);
|
||||
printf("%c%c%c%c%c%c%c%c\n", (buff[i] & 0x7F), (buff[i+1] & 0x7F), (buff[i+2] & 0x7F), (buff[i+3] & 0x7F), (buff[i+4] & 0x7F), (buff[i+5] & 0x7F), (buff[i+6] & 0x7F), (buff[i+7] & 0x7F));
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
// mmu_man 11/15/2002
|
||||
//ffc->frame_number = fFrame;
|
||||
|
||||
#ifdef DO_PROFILING
|
||||
prof_t1 = system_time();
|
||||
#endif
|
||||
|
||||
// PRINT(("avCodec::Decode(): before avcodec_decode_video()\n"));
|
||||
|
||||
|
||||
// len = avcodec_decode_video(ffc, &ffpicture, &got_picture, (uint8_t *)fData, fSize);
|
||||
len = avcodec_decode_video(ffc, ffpicture, &got_picture, (uint8_t *)fData, fSize);
|
||||
|
||||
// PRINT(("avCodec::Decode(): after avcodec_decode_video()\n"));
|
||||
|
||||
//printf("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);
|
||||
//printf("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] avCodec: error in decoding frame %lld\n", isAudio?('a'):('v'), *out_frameCount);
|
||||
|
||||
if (got_picture)
|
||||
{
|
||||
#ifdef DO_PROFILING
|
||||
prof_t2 = system_time();
|
||||
#endif
|
||||
PRINT(("ONE FRAME OUT !! len=%ld sz=%ld (%s)\n", len, fSize, pixfmt_to_string(ffc->pix_fmt)));
|
||||
/*
|
||||
opicture.data[0] = (uint8_t *)out_buffer;
|
||||
opicture.linesize[0] = fOutputVideoFormat.display.bytes_per_row;
|
||||
|
||||
(*conv_func)(&ffpicture, &opicture, fOutputVideoFormat.display.line_width, fOutputVideoFormat.display.line_count);
|
||||
*/
|
||||
opicture->data[0] = (uint8_t *)out_buffer;
|
||||
opicture->linesize[0] = fOutputVideoFormat.display.bytes_per_row;
|
||||
|
||||
// PRINT(("avCodec::Decode(): before conv_func()\n"));
|
||||
(*conv_func)(ffpicture, opicture, fOutputVideoFormat.display.line_width, fOutputVideoFormat.display.line_count);
|
||||
// PRINT(("avCodec::Decode(): after conv_func()\n"));
|
||||
#ifdef DEBUG
|
||||
dump_ffframe(ffpicture, "ffpict");
|
||||
// dump_ffframe(opicture, "opict");
|
||||
#endif
|
||||
*out_frameCount = 1;
|
||||
fFrame++;
|
||||
|
||||
#ifdef DO_PROFILING
|
||||
prof_t3 = system_time();
|
||||
diff1 += prof_t2 - prof_t1;
|
||||
diff2 += prof_t3 - prof_t2;
|
||||
prof_cnt++;
|
||||
if (!(fFrame % 10))
|
||||
printf("[%c] profile: d1 = %lld, d2 = %lld (%ld)\n", isAudio?('a'):('v'), diff1/prof_cnt, diff2/prof_cnt, fFrame);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// PRINT(("END of avCodec::Decode()\n"));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
avCodecPlugin::GetSupportedFormats(media_format ** formats, size_t * count)
|
||||
{
|
||||
BMediaFormats mediaFormats;
|
||||
if (B_OK != mediaFormats.InitCheck())
|
||||
return B_ERROR;
|
||||
|
||||
for (int i = 0; i < num_codecs; i++) {
|
||||
media_format_description description;
|
||||
description.family = gCodecTable[i].family;
|
||||
switch(description.family) {
|
||||
case B_WAV_FORMAT_FAMILY:
|
||||
description.u.wav.codec = gCodecTable[i].fourcc;
|
||||
break;
|
||||
case B_AVI_FORMAT_FAMILY:
|
||||
description.u.avi.codec = gCodecTable[i].fourcc;
|
||||
break;
|
||||
case B_MPEG_FORMAT_FAMILY:
|
||||
description.u.mpeg.id = gCodecTable[i].fourcc;
|
||||
break;
|
||||
case B_QUICKTIME_FORMAT_FAMILY:
|
||||
description.u.quicktime.codec = gCodecTable[i].fourcc;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
media_format format;
|
||||
format.type = gCodecTable[i].type;
|
||||
format.require_flags = 0;
|
||||
format.deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
|
||||
if (B_OK != mediaFormats.MakeFormatFor(&description, 1, &format))
|
||||
return B_ERROR;
|
||||
avcodec_formats[i] = format;
|
||||
}
|
||||
|
||||
*formats = avcodec_formats;
|
||||
*count = num_codecs;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
Decoder *
|
||||
avCodecPlugin::NewDecoder(uint index)
|
||||
{
|
||||
return new avCodec();
|
||||
}
|
||||
|
||||
|
||||
MediaPlugin *instantiate_plugin()
|
||||
{
|
||||
return new avCodecPlugin;
|
||||
}
|
||||
|
||||
|
@ -330,7 +330,7 @@ mp3Decoder::GetFrameLength(void *header)
|
||||
|
||||
|
||||
Decoder *
|
||||
mp3DecoderPlugin::NewDecoder()
|
||||
mp3DecoderPlugin::NewDecoder(uint index)
|
||||
{
|
||||
static BLocker locker;
|
||||
static bool initdone = false;
|
||||
@ -344,8 +344,10 @@ mp3DecoderPlugin::NewDecoder()
|
||||
}
|
||||
|
||||
|
||||
static media_format mp3_formats[1];
|
||||
|
||||
status_t
|
||||
mp3DecoderPlugin::RegisterDecoder()
|
||||
mp3DecoderPlugin::GetSupportedFormats(media_format ** formats, size_t * count)
|
||||
{
|
||||
const mpeg_id ids[] = {
|
||||
B_MPEG_1_AUDIO_LAYER_1,
|
||||
@ -374,12 +376,21 @@ mp3DecoderPlugin::RegisterDecoder()
|
||||
format.type = B_MEDIA_ENCODED_AUDIO;
|
||||
format.u.encoded_audio = media_encoded_audio_format::wildcard;
|
||||
|
||||
BMediaFormats formats;
|
||||
status_t result = formats.InitCheck();
|
||||
BMediaFormats mediaFormats;
|
||||
status_t result = mediaFormats.InitCheck();
|
||||
if (result != B_OK) {
|
||||
return result;
|
||||
}
|
||||
return formats.MakeFormatFor(descriptions, numIDs, &format);
|
||||
result = mediaFormats.MakeFormatFor(descriptions, numIDs, &format);
|
||||
if (result != B_OK) {
|
||||
return result;
|
||||
}
|
||||
mp3_formats[0] = format;
|
||||
|
||||
*formats = mp3_formats;
|
||||
*count = 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -46,6 +46,6 @@ private:
|
||||
class mp3DecoderPlugin : public DecoderPlugin
|
||||
{
|
||||
public:
|
||||
Decoder * NewDecoder();
|
||||
status_t RegisterDecoder();
|
||||
Decoder * NewDecoder(uint index);
|
||||
status_t GetSupportedFormats(media_format ** formats, size_t * count);
|
||||
};
|
||||
|
@ -16,13 +16,15 @@ MusePackPlugin::NewReader()
|
||||
}
|
||||
|
||||
Decoder *
|
||||
MusePackPlugin::NewDecoder()
|
||||
MusePackPlugin::NewDecoder(uint index)
|
||||
{
|
||||
return new MusePackDecoder();
|
||||
}
|
||||
|
||||
static media_format muse_pack_formats[1];
|
||||
|
||||
status_t
|
||||
MusePackPlugin::RegisterDecoder()
|
||||
MusePackPlugin::GetSupportedFormats(media_format ** formats, size_t * count)
|
||||
{
|
||||
media_format_description description;
|
||||
description.family = B_MISC_FORMAT_FAMILY;
|
||||
@ -34,7 +36,21 @@ MusePackPlugin::RegisterDecoder()
|
||||
format.type = B_MEDIA_ENCODED_AUDIO;
|
||||
format.u.encoded_audio = media_encoded_audio_format::wildcard;
|
||||
|
||||
return BMediaFormats().MakeFormatFor(&description, 1, &format);
|
||||
BMediaFormats mediaFormats;
|
||||
status_t result = mediaFormats.InitCheck();
|
||||
if (result != B_OK) {
|
||||
return result;
|
||||
}
|
||||
result = mediaFormats.MakeFormatFor(&description, 1, &format);
|
||||
if (result != B_OK) {
|
||||
return result;
|
||||
}
|
||||
muse_pack_formats[0] = format;
|
||||
|
||||
*formats = muse_pack_formats;
|
||||
*count = 1;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,8 +14,8 @@ class MusePackPlugin : public ReaderPlugin, public DecoderPlugin {
|
||||
public:
|
||||
Reader *NewReader();
|
||||
|
||||
Decoder *NewDecoder();
|
||||
status_t RegisterDecoder();
|
||||
Decoder * NewDecoder(uint index);
|
||||
status_t GetSupportedFormats(media_format ** formats, size_t * count);
|
||||
};
|
||||
|
||||
#endif /* MUSEPACK_PLUGIN_H */
|
||||
|
@ -106,8 +106,8 @@ OggTobiasStream::GetStreamInfo(int64 *frameCount, bigtime_t *duration,
|
||||
|
||||
// get the format for the description
|
||||
media_format_description description = tobias_description();
|
||||
description.u.avi.codec = header->subtype[0] << 24 | header->subtype[1] << 16
|
||||
| header->subtype[2] << 8 | header->subtype[3];
|
||||
description.u.avi.codec = header->subtype[3] << 24 | header->subtype[2] << 16
|
||||
| header->subtype[1] << 8 | header->subtype[0];
|
||||
BMediaFormats formats;
|
||||
result = formats.InitCheck();
|
||||
if (result == B_OK) {
|
||||
@ -141,3 +141,13 @@ OggTobiasStream::GetStreamInfo(int64 *frameCount, bigtime_t *duration,
|
||||
*frameCount = 60000;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
OggTobiasStream::GetNextChunk(void **chunkBuffer, int32 *chunkSize,
|
||||
media_header *mediaHeader)
|
||||
{
|
||||
OggStream::GetNextChunk(chunkBuffer, chunkSize, mediaHeader);
|
||||
*chunkSize = ((ogg_packet*)chunkBuffer)->bytes;
|
||||
*chunkBuffer = ((ogg_packet*)chunkBuffer)->packet;
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -14,6 +14,11 @@ public:
|
||||
|
||||
virtual status_t GetStreamInfo(int64 *frameCount, bigtime_t *duration,
|
||||
media_format *format);
|
||||
virtual status_t GetNextChunk(void **chunkBuffer, int32 *chunkSize,
|
||||
media_header *mediaHeader);
|
||||
private:
|
||||
ogg_packet fChunkPacket;
|
||||
|
||||
};
|
||||
|
||||
} } // namespace BPrivate::media
|
||||
|
@ -478,15 +478,18 @@ RawDecoder::Decode(void *buffer, int64 *frameCount,
|
||||
|
||||
|
||||
Decoder *
|
||||
RawDecoderPlugin::NewDecoder()
|
||||
RawDecoderPlugin::NewDecoder(uint index)
|
||||
{
|
||||
return new RawDecoder;
|
||||
}
|
||||
|
||||
|
||||
static media_format raw_formats[2];
|
||||
|
||||
status_t
|
||||
RawDecoderPlugin::RegisterDecoder()
|
||||
RawDecoderPlugin::GetSupportedFormats(media_format ** formats, size_t * count)
|
||||
{
|
||||
BMediaFormats formats;
|
||||
BMediaFormats mediaFormats;
|
||||
media_format_description description;
|
||||
media_format format;
|
||||
|
||||
@ -497,9 +500,10 @@ RawDecoderPlugin::RegisterDecoder()
|
||||
format.type = B_MEDIA_RAW_AUDIO;
|
||||
format.u.raw_audio = media_multi_audio_format::wildcard;
|
||||
|
||||
status_t status = formats.MakeFormatFor(&description, 1, &format);
|
||||
status_t status = mediaFormats.MakeFormatFor(&description, 1, &format);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
raw_formats[0] = format;
|
||||
|
||||
// video decoder
|
||||
|
||||
@ -507,7 +511,15 @@ RawDecoderPlugin::RegisterDecoder()
|
||||
format.type = B_MEDIA_RAW_VIDEO;
|
||||
format.u.raw_video = media_raw_video_format::wildcard;
|
||||
|
||||
return formats.MakeFormatFor(&description, 1, &format);
|
||||
status = mediaFormats.MakeFormatFor(&description, 1, &format);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
raw_formats[1] = format;
|
||||
|
||||
*formats = raw_formats;
|
||||
*count = 2;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
MediaPlugin *instantiate_plugin()
|
||||
|
@ -44,6 +44,6 @@ private:
|
||||
class RawDecoderPlugin : public DecoderPlugin
|
||||
{
|
||||
public:
|
||||
Decoder * NewDecoder();
|
||||
status_t RegisterDecoder();
|
||||
Decoder * NewDecoder(uint index);
|
||||
status_t GetSupportedFormats(media_format ** formats, size_t * count);
|
||||
};
|
||||
|
@ -315,7 +315,7 @@ done:
|
||||
|
||||
|
||||
Decoder *
|
||||
SpeexDecoderPlugin::NewDecoder()
|
||||
SpeexDecoderPlugin::NewDecoder(uint index)
|
||||
{
|
||||
static BLocker locker;
|
||||
static bool initdone = false;
|
||||
@ -327,18 +327,29 @@ SpeexDecoderPlugin::NewDecoder()
|
||||
}
|
||||
|
||||
|
||||
static media_format speex_formats[1];
|
||||
|
||||
status_t
|
||||
SpeexDecoderPlugin::RegisterDecoder()
|
||||
SpeexDecoderPlugin::GetSupportedFormats(media_format ** formats, size_t * count)
|
||||
{
|
||||
media_format_description description = speex_description();
|
||||
media_format format = speex_encoded_media_format();
|
||||
|
||||
BMediaFormats formats;
|
||||
status_t result = formats.InitCheck();
|
||||
BMediaFormats mediaFormats;
|
||||
status_t result = mediaFormats.InitCheck();
|
||||
if (result != B_OK) {
|
||||
return result;
|
||||
}
|
||||
return formats.MakeFormatFor(&description, 1, &format);
|
||||
result = mediaFormats.MakeFormatFor(&description, 1, &format);
|
||||
if (result != B_OK) {
|
||||
return result;
|
||||
}
|
||||
speex_formats[0] = format;
|
||||
|
||||
*formats = speex_formats;
|
||||
*count = 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -41,6 +41,6 @@ private:
|
||||
class SpeexDecoderPlugin : public DecoderPlugin
|
||||
{
|
||||
public:
|
||||
Decoder * NewDecoder();
|
||||
status_t RegisterDecoder();
|
||||
Decoder * NewDecoder(uint index);
|
||||
status_t GetSupportedFormats(media_format ** formats, size_t * count);
|
||||
};
|
||||
|
@ -246,7 +246,7 @@ done:
|
||||
|
||||
|
||||
Decoder *
|
||||
VorbisDecoderPlugin::NewDecoder()
|
||||
VorbisDecoderPlugin::NewDecoder(uint index)
|
||||
{
|
||||
static BLocker locker;
|
||||
static bool initdone = false;
|
||||
@ -257,18 +257,29 @@ VorbisDecoderPlugin::NewDecoder()
|
||||
return new VorbisDecoder;
|
||||
}
|
||||
|
||||
static media_format vorbis_formats[1];
|
||||
|
||||
status_t
|
||||
VorbisDecoderPlugin::RegisterDecoder()
|
||||
VorbisDecoderPlugin::GetSupportedFormats(media_format ** formats, size_t * count)
|
||||
{
|
||||
media_format_description description = vorbis_description();
|
||||
media_format format = vorbis_encoded_media_format();
|
||||
|
||||
BMediaFormats formats;
|
||||
status_t result = formats.InitCheck();
|
||||
BMediaFormats mediaFormats;
|
||||
status_t result = mediaFormats.InitCheck();
|
||||
if (result != B_OK) {
|
||||
return result;
|
||||
}
|
||||
return formats.MakeFormatFor(&description, 1, &format);
|
||||
result = mediaFormats.MakeFormatFor(&description, 1, &format);
|
||||
if (result != B_OK) {
|
||||
return result;
|
||||
}
|
||||
vorbis_formats[0] = format;
|
||||
|
||||
*formats = vorbis_formats;
|
||||
*count = 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,8 +39,8 @@ private:
|
||||
class VorbisDecoderPlugin : public DecoderPlugin
|
||||
{
|
||||
public:
|
||||
Decoder * NewDecoder();
|
||||
status_t RegisterDecoder();
|
||||
Decoder * NewDecoder(uint index);
|
||||
status_t GetSupportedFormats(media_format ** formats, size_t * count);
|
||||
};
|
||||
|
||||
#endif _VORBIS_CODEC_PLUGIN_H_
|
||||
|
@ -29,12 +29,17 @@ static port_id MediaAddonServerPort;
|
||||
void find_media_server_port();
|
||||
void find_media_addon_server_port();
|
||||
|
||||
static BMessenger * GetMediaServerMessenger() {
|
||||
static BMessenger * messenger = new BMessenger(NEW_MEDIA_SERVER_SIGNATURE);
|
||||
return MediaServerMessenger = messenger;
|
||||
}
|
||||
|
||||
class initit
|
||||
{
|
||||
public:
|
||||
initit()
|
||||
{
|
||||
MediaServerMessenger = new BMessenger(NEW_MEDIA_SERVER_SIGNATURE);
|
||||
MediaServerMessenger = 0;
|
||||
find_media_server_port();
|
||||
find_media_addon_server_port();
|
||||
|
||||
@ -82,7 +87,7 @@ request_data::SendReply(status_t result, reply_data *reply, int replysize) const
|
||||
status_t SendToServer(BMessage *msg)
|
||||
{
|
||||
status_t rv;
|
||||
rv = MediaServerMessenger->SendMessage(msg, static_cast<BHandler *>(NULL), TIMEOUT);
|
||||
rv = GetMediaServerMessenger()->SendMessage(msg, static_cast<BHandler *>(NULL), TIMEOUT);
|
||||
if (rv != B_OK) {
|
||||
ERROR("SendToServer: SendMessage failed, error 0x%08lx (%s)\n", rv, strerror(rv));
|
||||
DEBUG_ONLY(msg->PrintToStream());
|
||||
@ -94,7 +99,7 @@ status_t SendToServer(BMessage *msg)
|
||||
status_t
|
||||
QueryServer(BMessage &request, BMessage &reply)
|
||||
{
|
||||
status_t status = MediaServerMessenger->SendMessage(&request, &reply, TIMEOUT, TIMEOUT);
|
||||
status_t status = GetMediaServerMessenger()->SendMessage(&request, &reply, TIMEOUT, TIMEOUT);
|
||||
if (status != B_OK) {
|
||||
ERROR("QueryServer: SendMessage failed, error 0x%08lx (%s)\n", status, strerror(status));
|
||||
DEBUG_ONLY(request.PrintToStream());
|
||||
|
@ -125,7 +125,7 @@ BMediaDecoder::SetTo(const media_format *in_format,
|
||||
if (plugin == NULL) {
|
||||
return fInitStatus = B_ERROR;
|
||||
}
|
||||
Decoder * decoder = plugin->NewDecoder();
|
||||
Decoder * decoder = plugin->NewDecoder(0);
|
||||
if (decoder == NULL) {
|
||||
return fInitStatus = B_ERROR;
|
||||
}
|
||||
@ -163,7 +163,7 @@ BMediaDecoder::SetTo(const media_codec_info *mci)
|
||||
if (plugin == NULL) {
|
||||
return fInitStatus = B_ERROR;
|
||||
}
|
||||
Decoder * decoder = plugin->NewDecoder();
|
||||
Decoder * decoder = plugin->NewDecoder(0);
|
||||
if (decoder == NULL) {
|
||||
return fInitStatus = B_ERROR;
|
||||
}
|
||||
|
@ -24,8 +24,6 @@ static BLocker sLock;
|
||||
static BObjectList<meta_format> sFormats;
|
||||
static bigtime_t sLastFormatsUpdate;
|
||||
|
||||
_MakeFormatHookFunc BPrivate::media::_gMakeFormatHook = NULL;
|
||||
|
||||
|
||||
status_t
|
||||
get_next_encoder(int32 *cookie, const media_file_format *_fileFormat,
|
||||
@ -515,14 +513,43 @@ status_t
|
||||
BMediaFormats::MakeFormatFor(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags, void * _reserved)
|
||||
{
|
||||
if (_gMakeFormatHook == NULL)
|
||||
return B_NOT_ALLOWED;
|
||||
BMessage request(MEDIA_SERVER_MAKE_FORMAT_FOR);
|
||||
for (int32 i = 0 ; i < descriptionCount ; i++) {
|
||||
request.AddData("description", B_RAW_TYPE, &descriptions[i], sizeof(descriptions[i]));
|
||||
}
|
||||
request.AddData("format", B_RAW_TYPE, format, sizeof(*format));
|
||||
request.AddData("flags", B_UINT32_TYPE, &flags, sizeof(flags));
|
||||
request.AddPointer("_reserved", _reserved);
|
||||
|
||||
// This function is callable from the server in the
|
||||
// context of a codec registration only.
|
||||
// The add-on manager is locked during this call
|
||||
BMessage reply;
|
||||
status_t status = QueryServer(request, reply);
|
||||
if (status != B_OK) {
|
||||
ERROR("BMediaFormats: Could not make a format: %s\n", strerror(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
return _gMakeFormatHook(descriptions, descriptionCount, format, flags);
|
||||
// check the status
|
||||
if (reply.FindInt32("result", &status) < B_OK) {
|
||||
return B_ERROR;
|
||||
}
|
||||
if (status != B_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// get the format
|
||||
const void * data;
|
||||
ssize_t size;
|
||||
if (reply.FindData("format", B_RAW_TYPE, 0, &data, &size) != B_OK) {
|
||||
return B_ERROR;
|
||||
}
|
||||
if (size != sizeof(*format)) {
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// copy the BMessage's data into our format
|
||||
*format = *(media_format *)data;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* --- begin deprecated API --- */
|
||||
|
@ -100,7 +100,7 @@ _CreateDecoder(Decoder **_decoder, const media_format *format)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
*_decoder = decoderPlugin->NewDecoder();
|
||||
*_decoder = decoderPlugin->NewDecoder(0);
|
||||
if (*_decoder == NULL) {
|
||||
printf("_CreateDecoder: NewDecoder() failed\n");
|
||||
return B_ERROR;
|
||||
|
@ -31,6 +31,14 @@ AddOnMonitorHandler::MessageReceived(BMessage * msg)
|
||||
/* virtual */ status_t
|
||||
AddOnMonitorHandler::AddDirectory(const node_ref * nref)
|
||||
{
|
||||
// ignore directories added twice
|
||||
std::list<add_on_directory_info>::iterator diter = directories.begin();
|
||||
for( ; diter != directories.end() ; diter++) {
|
||||
if (diter->nref == *nref) {
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
|
||||
BDirectory directory(nref);
|
||||
status_t status = directory.InitCheck();
|
||||
if (status != B_OK) {
|
||||
|
@ -50,22 +50,6 @@ class ImageLoader {
|
||||
};
|
||||
|
||||
|
||||
static status_t
|
||||
register_decoder(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags)
|
||||
{
|
||||
return gAddOnManager->MakeDecoderFormats(descriptions, descriptionCount, format, flags);
|
||||
}
|
||||
|
||||
/* not yet used
|
||||
static status_t
|
||||
register_encoder(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags)
|
||||
{
|
||||
return gAddOnManager->MakeEncoderFormats(descriptions, descriptionCount, format, flags);
|
||||
}
|
||||
*/
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
@ -190,47 +174,62 @@ AddOnManager::RegisterAddOn(BEntry &entry)
|
||||
RegisterDecoder(decoder, ref);
|
||||
|
||||
delete plugin;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AddOnManager::RegisterAddOnsFor(BPath path)
|
||||
{
|
||||
path.Append("media/plugins");
|
||||
|
||||
BDirectory directory(path.Path());
|
||||
if (directory.InitCheck() != B_OK)
|
||||
return;
|
||||
|
||||
BEntry entry;
|
||||
while (directory.GetNextEntry(&entry) == B_OK)
|
||||
RegisterAddOn(entry);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AddOnManager::RegisterAddOns()
|
||||
{
|
||||
BPath path;
|
||||
|
||||
// user add-ons come first, so that they can lay over system
|
||||
// add-ons (add-ons are identified by name for registration)
|
||||
class CodecHandler : public AddOnMonitorHandler {
|
||||
private:
|
||||
AddOnManager * fManager;
|
||||
public:
|
||||
CodecHandler(AddOnManager * manager) {
|
||||
fManager = manager;
|
||||
}
|
||||
virtual void AddOnCreated(const add_on_entry_info * entry_info) {
|
||||
}
|
||||
virtual void AddOnEnabled(const add_on_entry_info * entry_info) {
|
||||
entry_ref ref;
|
||||
make_entry_ref(entry_info->dir_nref.device, entry_info->dir_nref.node,
|
||||
entry_info->name, &ref);
|
||||
BEntry entry(&ref, true);
|
||||
fManager->RegisterAddOn(entry);
|
||||
}
|
||||
virtual void AddOnDisabled(const add_on_entry_info * entry_info) {
|
||||
}
|
||||
virtual void AddOnRemoved(const add_on_entry_info * entry_info) {
|
||||
}
|
||||
};
|
||||
|
||||
const directory_which directories[] = {
|
||||
B_USER_ADDONS_DIRECTORY,
|
||||
B_COMMON_ADDONS_DIRECTORY,
|
||||
B_BEOS_ADDONS_DIRECTORY,
|
||||
};
|
||||
fHandler = new CodecHandler(this);
|
||||
fAddOnMonitor = new AddOnMonitor(fHandler);
|
||||
|
||||
for (uint32 i = 0; i < sizeof(directories) / sizeof(directory_which); i++) {
|
||||
if (find_directory(directories[i], &path) == B_OK)
|
||||
RegisterAddOnsFor(path);
|
||||
node_ref nref;
|
||||
BDirectory directory;
|
||||
BPath path;
|
||||
for (uint i = 0 ; i < sizeof(directories) / sizeof(directory_which) ; i++) {
|
||||
if ((find_directory(directories[i], &path) == B_OK)
|
||||
&& (path.Append("media/plugins") == B_OK)
|
||||
&& (directory.SetTo(path.Path()) == B_OK)
|
||||
&& (directory.GetNodeRef(&nref) == B_OK)) {
|
||||
fHandler->AddDirectory(&nref);
|
||||
}
|
||||
}
|
||||
|
||||
// ToDo: this is for our own convenience only, and should be removed
|
||||
// in the final release
|
||||
path.SetTo("/boot/home/develop/openbeos/current/distro/x86.R1/beos/system/add-ons");
|
||||
RegisterAddOnsFor(path);
|
||||
if ((directory.SetTo("/boot/home/develop/openbeos/current/distro/x86.R1/beos/system/add-ons/media/plugins") == B_OK)
|
||||
&& (directory.GetNodeRef(&nref) == B_OK)) {
|
||||
fHandler->AddDirectory(&nref);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -257,7 +256,7 @@ AddOnManager::RegisterReader(ReaderPlugin *reader, const entry_ref &ref)
|
||||
|
||||
|
||||
void
|
||||
AddOnManager::RegisterDecoder(DecoderPlugin *decoder, const entry_ref &ref)
|
||||
AddOnManager::RegisterDecoder(DecoderPlugin *plugin, const entry_ref &ref)
|
||||
{
|
||||
BAutolock locker(fLock);
|
||||
|
||||
@ -274,48 +273,16 @@ AddOnManager::RegisterDecoder(DecoderPlugin *decoder, const entry_ref &ref)
|
||||
decoder_info info;
|
||||
info.ref = ref;
|
||||
|
||||
fCurrentDecoder = &info;
|
||||
BPrivate::media::_gMakeFormatHook = register_decoder;
|
||||
|
||||
if (decoder->RegisterDecoder() != B_OK) {
|
||||
printf("AddOnManager::RegisterDecoder(): decoder->RegisterDecoder() failed!\n");
|
||||
media_format * formats = 0;
|
||||
size_t count = 0;
|
||||
if (plugin->GetSupportedFormats(&formats,&count) != B_OK) {
|
||||
printf("AddOnManager::RegisterDecoder(): plugin->GetSupportedFormats(...) failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint i = 0 ; i < count ; i++) {
|
||||
info.formats.Insert(formats[i]);
|
||||
}
|
||||
fDecoderList.Insert(info);
|
||||
fCurrentDecoder = NULL;
|
||||
BPrivate::media::_gMakeFormatHook = NULL;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AddOnManager::MakeEncoderFormats(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags)
|
||||
{
|
||||
//ASSERT(fCurrentEncoder != NULL);
|
||||
|
||||
status_t status = gFormatManager->RegisterEncoder(descriptions,
|
||||
descriptionCount, format, flags);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
//fCurrentEncoder->format = *format;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AddOnManager::MakeDecoderFormats(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags)
|
||||
{
|
||||
ASSERT(fCurrentDecoder != NULL);
|
||||
|
||||
status_t status = gFormatManager->RegisterDecoder(descriptions,
|
||||
descriptionCount, format, flags);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
fCurrentDecoder->formats.Insert(*format);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "DataExchange.h"
|
||||
#include "TList.h"
|
||||
|
||||
#include "AddOnMonitor.h"
|
||||
#include "AddOnMonitorHandler.h"
|
||||
|
||||
class AddOnManager {
|
||||
public:
|
||||
@ -30,14 +32,8 @@ class AddOnManager {
|
||||
status_t GetReaders(xfer_entry_ref *out_res, int32 *out_count,
|
||||
int32 max_count);
|
||||
|
||||
status_t MakeEncoderFormats(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags);
|
||||
status_t MakeDecoderFormats(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags);
|
||||
|
||||
private:
|
||||
status_t RegisterAddOn(BEntry &entry);
|
||||
void RegisterAddOnsFor(BPath path);
|
||||
void RegisterAddOns();
|
||||
|
||||
void RegisterReader(ReaderPlugin *reader, const entry_ref &ref);
|
||||
@ -65,6 +61,9 @@ class AddOnManager {
|
||||
List<encoder_info> fEncoderList;
|
||||
|
||||
decoder_info *fCurrentDecoder;
|
||||
|
||||
AddOnMonitorHandler *fHandler;
|
||||
AddOnMonitor *fAddOnMonitor;
|
||||
};
|
||||
|
||||
#endif // _ADD_ON_MANAGER_H
|
||||
|
@ -77,74 +77,82 @@ FormatManager::GetFormats(BMessage &message)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FormatManager::RegisterDecoder(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags)
|
||||
{
|
||||
return RegisterDescriptions(descriptions, descriptionCount, format, flags, false);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FormatManager::RegisterEncoder(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags)
|
||||
{
|
||||
return RegisterDescriptions(descriptions, descriptionCount, format, flags, true);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FormatManager::RegisterDescriptions(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags, bool encoder)
|
||||
void
|
||||
FormatManager::MakeFormatFor(BMessage &message)
|
||||
{
|
||||
BAutolock locker(fLock);
|
||||
|
||||
int32 codec = fNextCodecID++;
|
||||
fLastUpdate = system_time();
|
||||
media_format format;
|
||||
const void * data;
|
||||
ssize_t size;
|
||||
if (message.FindData("format", B_RAW_TYPE, 0, &data, &size) != B_OK
|
||||
|| size != sizeof(format)) {
|
||||
// couldn't get the format
|
||||
BMessage reply;
|
||||
reply.AddInt32("result", B_ERROR);
|
||||
message.SendReply(&reply, (BHandler *)NULL, TIMEOUT);
|
||||
return;
|
||||
}
|
||||
// copy the BMessage's data into our format
|
||||
format = *(media_format *)data;
|
||||
|
||||
switch (format->type) {
|
||||
int codec = fNextCodecID;
|
||||
switch (format.type) {
|
||||
case B_MEDIA_RAW_AUDIO:
|
||||
case B_MEDIA_RAW_VIDEO:
|
||||
// no marker
|
||||
break;
|
||||
case B_MEDIA_ENCODED_AUDIO:
|
||||
format->u.encoded_audio.encoding = (media_encoded_audio_format::audio_encoding)codec;
|
||||
if (format.u.encoded_audio.encoding == 0) {
|
||||
format.u.encoded_audio.encoding = (media_encoded_audio_format::audio_encoding)fNextCodecID++;
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
// TODO: check the encoding and the format passed in for compatibility
|
||||
// return B_MISMATCHED_VALUES if incompatible - perhaps something else based on flags?
|
||||
}
|
||||
break;
|
||||
case B_MEDIA_ENCODED_VIDEO:
|
||||
format->u.encoded_video.encoding = (media_encoded_video_format::video_encoding)codec;
|
||||
if (format.u.encoded_video.encoding == 0) {
|
||||
format.u.encoded_video.encoding = (media_encoded_video_format::video_encoding)fNextCodecID++;
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
// TODO: check the encoding and the format passed in for compatibility
|
||||
// return B_MISMATCHED_VALUES if incompatible - perhaps something else based on flags?
|
||||
}
|
||||
break;
|
||||
case B_MEDIA_MULTISTREAM:
|
||||
format->u.multistream.format = codec;
|
||||
if (format.u.multistream.format == 0) {
|
||||
format.u.multistream.format = fNextCodecID++;
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
// TODO: check the encoding and the format passed in for compatibility
|
||||
// return B_MISMATCHED_VALUES if incompatible - perhaps something else based on flags?
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// ToDo: what can we do for the raw formats?
|
||||
break;
|
||||
// nothing to do
|
||||
BMessage reply;
|
||||
reply.AddInt32("result", B_OK);
|
||||
reply.AddData("format", B_RAW_TYPE, &format, sizeof(format));
|
||||
message.SendReply(&reply, (BHandler *)NULL, TIMEOUT);
|
||||
return;
|
||||
}
|
||||
fLastUpdate = system_time();
|
||||
|
||||
// ToDo: support "flags" (B_SET_DEFAULT, B_EXCLUSIVE, B_NO_MERGE)!
|
||||
|
||||
for (int32 i = 0; i < descriptionCount; i++) {
|
||||
meta_format *metaFormat = new meta_format(descriptions[i], *format, codec);
|
||||
|
||||
if (encoder)
|
||||
fEncoderFormats.BinaryInsert(metaFormat, meta_format::Compare);
|
||||
else
|
||||
fDecoderFormats.BinaryInsert(metaFormat, meta_format::Compare);
|
||||
int32 i = 0;
|
||||
while (message.FindData("description", B_RAW_TYPE, i++, &data, &size) == B_OK
|
||||
&& size == sizeof(media_format_description)) {
|
||||
meta_format *metaFormat = new meta_format(*(media_format_description*)data, format, codec);
|
||||
|
||||
fList.BinaryInsert(metaFormat, meta_format::Compare);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FormatManager::UnregisterDecoder(media_format &format)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FormatManager::UnregisterEncoder(media_format &format)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
BMessage reply;
|
||||
reply.AddInt32("result", B_OK);
|
||||
reply.AddData("format", B_RAW_TYPE, &format, sizeof(format));
|
||||
message.SendReply(&reply, (BHandler *)NULL, TIMEOUT);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,25 +17,11 @@ class FormatManager {
|
||||
void SaveState();
|
||||
|
||||
void GetFormats(BMessage &message);
|
||||
|
||||
status_t RegisterDecoder(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags);
|
||||
status_t RegisterEncoder(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags);
|
||||
|
||||
void UnregisterDecoder(media_format &format);
|
||||
void UnregisterEncoder(media_format &format);
|
||||
|
||||
private:
|
||||
status_t RegisterDescriptions(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags,
|
||||
bool encoder);
|
||||
void MakeFormatFor(BMessage &message);
|
||||
|
||||
private:
|
||||
typedef BPrivate::media::meta_format meta_format;
|
||||
|
||||
BObjectList<meta_format> fDecoderFormats;
|
||||
BObjectList<meta_format> fEncoderFormats;
|
||||
BObjectList<meta_format> fList;
|
||||
BLocker fLock;
|
||||
bigtime_t fLastUpdate;
|
||||
|
@ -2,6 +2,7 @@ SubDir OBOS_TOP src servers media ;
|
||||
|
||||
UsePrivateHeaders media ;
|
||||
UsePrivateHeaders shared ;
|
||||
UsePrivateHeaders storage ;
|
||||
|
||||
AddResources media_server : media_server.rdef ;
|
||||
|
||||
@ -16,5 +17,14 @@ Server media_server :
|
||||
NodeManager.cpp
|
||||
NotificationManager.cpp
|
||||
Queue.cpp
|
||||
|
||||
# storage
|
||||
AddOnMonitor.cpp
|
||||
AddOnMonitorHandler.cpp
|
||||
NodeMonitorHandler.cpp
|
||||
;
|
||||
LinkSharedOSLibs media_server : be libmedia.so ;
|
||||
|
||||
SEARCH on [ FGristFiles AddOnMonitor.cpp
|
||||
AddOnMonitorHandler.cpp
|
||||
NodeMonitorHandler.cpp ] += [ FDirName $(SUBDIR) .. .. kits storage ] ;
|
||||
|
@ -112,6 +112,7 @@ private:
|
||||
BLocker *fLocker;
|
||||
|
||||
virtual void MessageReceived(BMessage *msg);
|
||||
virtual void ReadyToRun();
|
||||
typedef BApplication inherited;
|
||||
};
|
||||
|
||||
@ -134,8 +135,13 @@ ServerApp::ServerApp()
|
||||
// StartSystemTimeSource();
|
||||
gNodeManager->LoadState();
|
||||
gFormatManager->LoadState();
|
||||
gAddOnManager->LoadState();
|
||||
gAppManager->StartAddonServer();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ServerApp::ReadyToRun()
|
||||
{
|
||||
be_app_messenger.SendMessage(MEDIA_SERVER_READY);
|
||||
}
|
||||
|
||||
ServerApp::~ServerApp()
|
||||
@ -726,6 +732,11 @@ ServerApp::MessageReceived(BMessage *msg)
|
||||
{
|
||||
TRACE("ServerApp::MessageReceived %lx enter\n", msg->what);
|
||||
switch (msg->what) {
|
||||
case MEDIA_SERVER_READY:
|
||||
gAppManager->StartAddonServer();
|
||||
gAddOnManager->LoadState();
|
||||
break;
|
||||
|
||||
case MEDIA_SERVER_REQUEST_NOTIFICATIONS:
|
||||
case MEDIA_SERVER_CANCEL_NOTIFICATIONS:
|
||||
case MEDIA_SERVER_SEND_NOTIFICATIONS:
|
||||
@ -740,6 +751,10 @@ ServerApp::MessageReceived(BMessage *msg)
|
||||
gFormatManager->GetFormats(*msg);
|
||||
break;
|
||||
|
||||
case MEDIA_SERVER_MAKE_FORMAT_FOR:
|
||||
gFormatManager->MakeFormatFor(*msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
inherited::MessageReceived(msg);
|
||||
//printf("\nnew media server: unknown message received\n");
|
||||
|
Loading…
Reference in New Issue
Block a user