From fa8dbc019dd3bd72a121c30ff5838f71f5185a7b Mon Sep 17 00:00:00 2001 From: shatty Date: Mon, 2 Feb 2004 05:26:40 +0000 Subject: [PATCH] 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 --- headers/private/media/DataExchange.h | 3 + headers/private/media/DecoderPlugin.h | 4 +- src/add-ons/media/plugins/avcodec/avcodec.cpp | 692 +++++++++++++++++- .../plugins/mp3_decoder/mp3DecoderPlugin.cpp | 21 +- .../plugins/mp3_decoder/mp3DecoderPlugin.h | 4 +- .../media/plugins/musepack/MusePack.cpp | 22 +- src/add-ons/media/plugins/musepack/MusePack.h | 4 +- .../media/plugins/ogg/OggTobiasStream.cpp | 14 +- .../media/plugins/ogg/OggTobiasStream.h | 5 + .../plugins/raw_decoder/RawDecoderPlugin.cpp | 22 +- .../plugins/raw_decoder/RawDecoderPlugin.h | 4 +- .../media/plugins/speex/speexCodecPlugin.cpp | 21 +- .../media/plugins/speex/speexCodecPlugin.h | 4 +- .../plugins/vorbis/vorbisCodecPlugin.cpp | 21 +- .../media/plugins/vorbis/vorbisCodecPlugin.h | 4 +- src/kits/media/DataExchange.cpp | 11 +- src/kits/media/MediaDecoder.cpp | 4 +- src/kits/media/MediaFormats.cpp | 43 +- src/kits/media/PluginManager.cpp | 2 +- src/kits/storage/AddOnMonitorHandler.cpp | 8 + src/servers/media/AddOnManager.cpp | 127 ++-- src/servers/media/AddOnManager.h | 11 +- src/servers/media/FormatManager.cpp | 108 +-- src/servers/media/FormatManager.h | 16 +- src/servers/media/Jamfile | 10 + src/servers/media/media_server.cpp | 19 +- 26 files changed, 999 insertions(+), 205 deletions(-) diff --git a/headers/private/media/DataExchange.h b/headers/private/media/DataExchange.h index 6b3ce770d1..536380e323 100644 --- a/headers/private/media/DataExchange.h +++ b/headers/private/media/DataExchange.h @@ -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 diff --git a/headers/private/media/DecoderPlugin.h b/headers/private/media/DecoderPlugin.h index 49693ee3b2..e9f46c55e3 100644 --- a/headers/private/media/DecoderPlugin.h +++ b/headers/private/media/DecoderPlugin.h @@ -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 diff --git a/src/add-ons/media/plugins/avcodec/avcodec.cpp b/src/add-ons/media/plugins/avcodec/avcodec.cpp index 74a86e1d03..ee04ad63a3 100644 --- a/src/add-ons/media/plugins/avcodec/avcodec.cpp +++ b/src/add-ons/media/plugins/avcodec/avcodec.cpp @@ -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 +#include +#include +#include +#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; itype), 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; +} + diff --git a/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.cpp b/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.cpp index 609b8c20e7..7c28443c2c 100644 --- a/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.cpp +++ b/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.cpp @@ -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; } diff --git a/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.h b/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.h index da29ae17af..bac581738d 100644 --- a/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.h +++ b/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.h @@ -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); }; diff --git a/src/add-ons/media/plugins/musepack/MusePack.cpp b/src/add-ons/media/plugins/musepack/MusePack.cpp index a11f546bac..c5f6835208 100644 --- a/src/add-ons/media/plugins/musepack/MusePack.cpp +++ b/src/add-ons/media/plugins/musepack/MusePack.cpp @@ -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; } diff --git a/src/add-ons/media/plugins/musepack/MusePack.h b/src/add-ons/media/plugins/musepack/MusePack.h index 9c5e1c78e3..40a8e6fb4f 100644 --- a/src/add-ons/media/plugins/musepack/MusePack.h +++ b/src/add-ons/media/plugins/musepack/MusePack.h @@ -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 */ diff --git a/src/add-ons/media/plugins/ogg/OggTobiasStream.cpp b/src/add-ons/media/plugins/ogg/OggTobiasStream.cpp index fe5a4ee4a2..7843c29b6b 100644 --- a/src/add-ons/media/plugins/ogg/OggTobiasStream.cpp +++ b/src/add-ons/media/plugins/ogg/OggTobiasStream.cpp @@ -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; +} diff --git a/src/add-ons/media/plugins/ogg/OggTobiasStream.h b/src/add-ons/media/plugins/ogg/OggTobiasStream.h index 8e150bd18c..c05edec1f9 100644 --- a/src/add-ons/media/plugins/ogg/OggTobiasStream.h +++ b/src/add-ons/media/plugins/ogg/OggTobiasStream.h @@ -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 diff --git a/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp index f3c7730608..949dc29c0f 100644 --- a/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp +++ b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp @@ -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() diff --git a/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h index cc662c8342..262278b2a5 100644 --- a/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h +++ b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h @@ -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); }; diff --git a/src/add-ons/media/plugins/speex/speexCodecPlugin.cpp b/src/add-ons/media/plugins/speex/speexCodecPlugin.cpp index ba25cde51f..8592fb89d7 100644 --- a/src/add-ons/media/plugins/speex/speexCodecPlugin.cpp +++ b/src/add-ons/media/plugins/speex/speexCodecPlugin.cpp @@ -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; } diff --git a/src/add-ons/media/plugins/speex/speexCodecPlugin.h b/src/add-ons/media/plugins/speex/speexCodecPlugin.h index cedb8286a1..1827a1abd4 100644 --- a/src/add-ons/media/plugins/speex/speexCodecPlugin.h +++ b/src/add-ons/media/plugins/speex/speexCodecPlugin.h @@ -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); }; diff --git a/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.cpp b/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.cpp index 959ba0cf3b..bc7669ef78 100644 --- a/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.cpp +++ b/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.cpp @@ -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; } diff --git a/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.h b/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.h index d5082eadac..40e61d7da7 100644 --- a/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.h +++ b/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.h @@ -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_ diff --git a/src/kits/media/DataExchange.cpp b/src/kits/media/DataExchange.cpp index 2f59a986d5..92edb7512b 100644 --- a/src/kits/media/DataExchange.cpp +++ b/src/kits/media/DataExchange.cpp @@ -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(NULL), TIMEOUT); + rv = GetMediaServerMessenger()->SendMessage(msg, static_cast(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()); diff --git a/src/kits/media/MediaDecoder.cpp b/src/kits/media/MediaDecoder.cpp index 8b743540cb..b2e1c33af6 100644 --- a/src/kits/media/MediaDecoder.cpp +++ b/src/kits/media/MediaDecoder.cpp @@ -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; } diff --git a/src/kits/media/MediaFormats.cpp b/src/kits/media/MediaFormats.cpp index e330563d3b..824ffb9919 100644 --- a/src/kits/media/MediaFormats.cpp +++ b/src/kits/media/MediaFormats.cpp @@ -24,8 +24,6 @@ static BLocker sLock; static BObjectList 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); + + 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; + } - // This function is callable from the server in the - // context of a codec registration only. - // The add-on manager is locked during this call + // check the status + if (reply.FindInt32("result", &status) < B_OK) { + return B_ERROR; + } + if (status != B_OK) { + return status; + } - return _gMakeFormatHook(descriptions, descriptionCount, format, flags); + // 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 --- */ diff --git a/src/kits/media/PluginManager.cpp b/src/kits/media/PluginManager.cpp index e3d766952c..cc2c4d9349 100644 --- a/src/kits/media/PluginManager.cpp +++ b/src/kits/media/PluginManager.cpp @@ -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; diff --git a/src/kits/storage/AddOnMonitorHandler.cpp b/src/kits/storage/AddOnMonitorHandler.cpp index 687fc942ae..2c7de982d1 100644 --- a/src/kits/storage/AddOnMonitorHandler.cpp +++ b/src/kits/storage/AddOnMonitorHandler.cpp @@ -31,6 +31,14 @@ AddOnMonitorHandler::MessageReceived(BMessage * msg) /* virtual */ status_t AddOnMonitorHandler::AddDirectory(const node_ref * nref) { + // ignore directories added twice + std::list::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) { diff --git a/src/servers/media/AddOnManager.cpp b/src/servers/media/AddOnManager.cpp index 1ebed73a21..45dea7a683 100644 --- a/src/servers/media/AddOnManager.cpp +++ b/src/servers/media/AddOnManager.cpp @@ -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; -} - diff --git a/src/servers/media/AddOnManager.h b/src/servers/media/AddOnManager.h index 22e3295b43..c39eba88f6 100644 --- a/src/servers/media/AddOnManager.h +++ b/src/servers/media/AddOnManager.h @@ -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 fEncoderList; decoder_info *fCurrentDecoder; + + AddOnMonitorHandler *fHandler; + AddOnMonitor *fAddOnMonitor; }; #endif // _ADD_ON_MANAGER_H diff --git a/src/servers/media/FormatManager.cpp b/src/servers/media/FormatManager.cpp index 8fc6d7abd8..96b4fdc449 100644 --- a/src/servers/media/FormatManager.cpp +++ b/src/servers/media/FormatManager.cpp @@ -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; } diff --git a/src/servers/media/FormatManager.h b/src/servers/media/FormatManager.h index 26ac1292c9..46a8d2d762 100644 --- a/src/servers/media/FormatManager.h +++ b/src/servers/media/FormatManager.h @@ -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 fDecoderFormats; - BObjectList fEncoderFormats; BObjectList fList; BLocker fLock; bigtime_t fLastUpdate; diff --git a/src/servers/media/Jamfile b/src/servers/media/Jamfile index 52583c2121..61d5dd7dd7 100644 --- a/src/servers/media/Jamfile +++ b/src/servers/media/Jamfile @@ -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 ] ; diff --git a/src/servers/media/media_server.cpp b/src/servers/media/media_server.cpp index 620390bc7b..5f0073fe5c 100644 --- a/src/servers/media/media_server.cpp +++ b/src/servers/media/media_server.cpp @@ -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");