Author: rolf
Date: 2008-01-11 09:50:22 -0500 (Fri, 11 Jan 2008)
New Revision: 92670

Modified:
   trunk/moon/src/ChangeLog
   trunk/moon/src/media.cpp
   trunk/moon/src/mplayer.cpp
   trunk/moon/src/mplayer2.cpp
   trunk/moon/src/pipeline-ffmpeg.cpp
   trunk/moon/src/pipeline-ffmpeg.h
   trunk/moon/src/pipeline.cpp
   trunk/moon/src/pipeline.h
Log:
* media.cpp: Initialize Media too upon initialization.
* pipeline.cpp, pipeline.h, pipeline-ffmpeg.cpp, pipeline-ffmpeg.h,
  mplayer2.cpp, mplayer.cpp: Implement registration of components,
  making it possible to completely remove ffmpeg.

Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog    2008-01-11 14:48:10 UTC (rev 92669)
+++ trunk/moon/src/ChangeLog    2008-01-11 14:50:22 UTC (rev 92670)
@@ -1,5 +1,12 @@
 2008-01-11  Rolf Bjarne Kvinge <[EMAIL PROTECTED]> 
 
+       * media.cpp: Initialize Media too upon initialization.
+       * pipeline.cpp, pipeline.h, pipeline-ffmpeg.cpp, pipeline-ffmpeg.h,
+         mplayer2.cpp, mplayer.cpp: Implement registration of components, 
making
+         it possible to completely remove ffmpeg.
+
+2008-01-11  Rolf Bjarne Kvinge <[EMAIL PROTECTED]> 
+
        * pipeline.cpp: Remove stray character.
 
 2008-01-11  Rolf Bjarne Kvinge <[EMAIL PROTECTED]> 

Modified: trunk/moon/src/media.cpp
===================================================================
--- trunk/moon/src/media.cpp    2008-01-11 14:48:10 UTC (rev 92669)
+++ trunk/moon/src/media.cpp    2008-01-11 14:50:22 UTC (rev 92670)
@@ -26,6 +26,7 @@
 #include "downloader.h"
 #include "playlist.h"
 #include "geometry.h"
+#include "pipeline.h"
 
 // still too ugly to be exposed in the header files ;-)
 cairo_pattern_t *image_brush_create_pattern (cairo_t *cairo, cairo_surface_t 
*surface, int sw, int sh, double opacity);
@@ -1831,4 +1832,8 @@
 
        t = Type::Find (Type::IMAGE);
        Image::ImageFailedEvent = t->LookupEvent ("ImageFailed");
+       
+#ifdef MOON_MEDIA
+       Media::Initialize ();
+#endif
 }

Modified: trunk/moon/src/mplayer.cpp
===================================================================
--- trunk/moon/src/mplayer.cpp  2008-01-11 14:48:10 UTC (rev 92669)
+++ trunk/moon/src/mplayer.cpp  2008-01-11 14:50:22 UTC (rev 92670)
@@ -12,6 +12,9 @@
 #include <config.h>
 #endif
 
+#include "pipeline.h"
+#ifndef MOON_MEDIA
+
 #include <glib.h>
 
 #include <poll.h>
@@ -34,13 +37,11 @@
 
 #include "clock.h"
 #include "mplayer.h"
-#include "pipeline.h"
 //#include "stream.h"
 #include "asf/asf-ffmpeg.h"
 #include "runtime.h"
 #include "list.h"
 
-#ifndef MOON_MEDIA
 
 #if GLIB_SIZEOF_VOID_P == 8
 #define ALIGN(addr,size) (uint8_t *) (((uint64_t) (((uint8_t *) (addr)) + 
(size) - 1)) & ~((size) - 1))
@@ -593,8 +594,10 @@
        
        video->queue->Unlock ();
        
-       if (update)
+       if (update) {
+               //printf ("advancing to video frame with pts: %lld\n", 
current_pts);
                convert_to_rgb (video, frame);
+       }
        
        if (frame != NULL) {
                av_free (frame);

Modified: trunk/moon/src/mplayer2.cpp
===================================================================
--- trunk/moon/src/mplayer2.cpp 2008-01-11 14:48:10 UTC (rev 92669)
+++ trunk/moon/src/mplayer2.cpp 2008-01-11 14:50:22 UTC (rev 92670)
@@ -29,7 +29,6 @@
 G_BEGIN_DECLS
 #include <stdint.h>
 #include <limits.h>
-#include <swscale.h>
 G_END_DECLS
 
 #include "clock.h"
@@ -193,7 +192,7 @@
        IMediaDecoder *codec;
        
        // rendering
-       struct SwsContext *scaler;
+       //struct SwsContext *scaler;
        cairo_surface_t *surface;
        uint8_t *rgb_buffer;
        
@@ -213,7 +212,7 @@
        stream = NULL;
        codec = NULL;
        
-       scaler = NULL;
+       //scaler = NULL;
        surface = NULL;
        rgb_buffer = NULL;
        
@@ -275,13 +274,15 @@
        
        g_free (uri);
        
+       Media* media = NULL;
        if (audio->media != NULL) {
-               delete audio->media;
+               media = audio->media;
        } else if (video->media != NULL) {
-               delete video->media;
+               media = video->media;
        }
        delete audio;
        delete video;
+       delete media;
 }
 
 MediaResult
@@ -380,10 +381,10 @@
                        
                        // for conversion to rgb32 format needed for rendering
                        video->rgb_buffer = (uint8_t *) g_malloc0 (width * 
height * 4);
-                       video->scaler = sws_getContext (width, height, 
encoding->pixel_format,
+                       /*video->scaler = sws_getContext (width, height, 
encoding->pixel_format,
                                                        width, height, 
PIX_FMT_RGB32,
                                                        SWS_BICUBIC, NULL, 
NULL, NULL);
-                       
+                       */
                        // rendering surface
                        video->surface = cairo_image_surface_create_for_data (
                                video->rgb_buffer, CAIRO_FORMAT_ARGB32,

Modified: trunk/moon/src/pipeline-ffmpeg.cpp
===================================================================
--- trunk/moon/src/pipeline-ffmpeg.cpp  2008-01-11 14:48:10 UTC (rev 92669)
+++ trunk/moon/src/pipeline-ffmpeg.cpp  2008-01-11 14:50:22 UTC (rev 92670)
@@ -35,6 +35,7 @@
 #include "debug.h"
 
 bool ffmpeg_initialized = false;
+bool ffmpeg_registered = false;
 
 void
 initialize_ffmpeg ()
@@ -48,7 +49,25 @@
        ffmpeg_initialized = true;
 }
 
+void
+register_ffmpeg ()
+{
+       initialize_ffmpeg ();
+       
+       if (ffmpeg_registered)
+               return;
+               
+       Media::RegisterConverter (new FfmpegConverterInfo ());
+       Media::RegisterDecoder (new FfmpegDecoderInfo ());
+       //Media::RegisterDemuxer (new FfmpegDemuxerInfo ());
+       
+       ffmpeg_registered = true;
+}
 
+/*
+ * FfmpegDecoder
+ */
+
 FfmpegDecoder::FfmpegDecoder (Media* media, IMediaStream* stream) 
        : IMediaDecoder (media, stream),
        audio_buffer (NULL)
@@ -156,6 +175,16 @@
        audio_buffer = NULL;
 }
 
+void
+FfmpegDecoder::Cleanup (MediaFrame* frame)
+{
+       AVFrame* av_frame = (AVFrame*) frame->decoder_specific_data;
+       if (av_frame != NULL) {
+               av_free (av_frame);
+               frame->decoder_specific_data = NULL;
+       }
+}
+
 MediaResult
 FfmpegDecoder::DecodeFrame (MediaFrame* media_frame)
 {
@@ -173,7 +202,7 @@
        //printf ("\n");
        
        if (stream->GetType () == MediaTypeVideo) {
-               VideoStream* vs = (VideoStream*) stream;
+       //      VideoStream* vs = (VideoStream*) stream;
                
                frame = avcodec_alloc_frame ();
        
@@ -190,8 +219,8 @@
                        media_frame->uncompressed_size = context->width * 
context->height * 4;
                        media_frame->uncompressed_data = (uint8_t*) g_malloc 
(media_frame->uncompressed_size);
                        
-                       uint8_t *rgb_dest[3] = { (uint8_t*) 
media_frame->uncompressed_data, NULL, NULL};
-                       int rgb_stride [3] = { context->width * 4, 0, 0 };
+       //              uint8_t *rgb_dest[3] = { (uint8_t*) 
media_frame->uncompressed_data, NULL, NULL};
+       //              int rgb_stride [3] = { context->width * 4, 0, 0 };
                        
                        for (int i = 0; i < 4; i++) {
                                media_frame->uncompressed_data_stride [i] = 
frame->data [i];
@@ -236,5 +265,121 @@
        return MEDIA_SUCCESS;
 }
 
+/*
+ * FfmpegDecoderInfo
+ */
+
+bool
+FfmpegDecoderInfo::Supports (const char* codec)
+{
+       return avcodec_find_decoder_by_name (codec) != NULL;
+}
+
+IMediaDecoder*
+FfmpegDecoderInfo::Create (Media* media, IMediaStream* stream)
+{
+       return new FfmpegDecoder (media, stream);
+}
+
+
+/*
+ * FfmpegConverter
+ */
+
+FfmpegConverter::FfmpegConverter (Media* media, VideoStream* stream) : 
IImageConverter (media, stream)
+{
+       scaler = NULL;
+}
+
+FfmpegConverter::~FfmpegConverter ()
+{
+       if (scaler != NULL) {
+               sws_freeContext (scaler);
+               scaler = NULL;
+       }
+}
+
+PixelFormat 
+FfmpegConverter::ToFfmpegPixFmt (MoonPixelFormat format)
+{
+       switch (format) {
+       case MoonPixelFormatYUV420P: return PIX_FMT_YUV420P;  
+       case MoonPixelFormatRGB32: return PIX_FMT_RGB32;
+       default:
+               printf ("FfmpegConverter::ToFfmpegPixFmt (%i): Unknown pixel 
format.\n", format);
+               return PIX_FMT_NONE;
+       }
+}
+
+MoonPixelFormat
+FfmpegConverter::ToMoonPixFmt (PixelFormat format)
+{
+       switch (format) {
+       case PIX_FMT_YUV420P: return MoonPixelFormatYUV420P;
+       case PIX_FMT_RGB32: return MoonPixelFormatRGB32;
+       default:
+               printf ("FfmpegConverter::ToMoonPixFmt (%i): Unknown pixel 
format.\n", format);
+               return MoonPixelFormatNone;
+       };
+}
+
+MediaResult
+FfmpegConverter::Open ()
+{
+       PixelFormat in_format = ToFfmpegPixFmt (input_format);
+       PixelFormat out_format = ToFfmpegPixFmt (output_format);
+       
+       if (in_format == PIX_FMT_NONE) {
+               media->AddMessage (MEDIA_CONVERTER_ERROR, "Invalid input 
format.");
+               return MEDIA_CONVERTER_ERROR;
+       }
+       
+       if (out_format == PIX_FMT_NONE) {
+               media->AddMessage (MEDIA_CONVERTER_ERROR, "Invalid output 
format.");
+               return MEDIA_CONVERTER_ERROR;
+       }
+       
+       scaler = sws_getContext (stream->width, stream->height, in_format,
+                       stream->width, stream->height, out_format,
+                       SWS_BICUBIC, NULL, NULL, NULL);
+                       
+       return MEDIA_SUCCESS;
+}
+
+MediaResult
+FfmpegConverter::Convert (uint8_t *src[], int srcStride[], int srcSlideY, int 
srcSlideH, uint8_t* dest[], int dstStride [])
+{
+       if (scaler == NULL) {
+               media->AddMessage (MEDIA_CONVERTER_ERROR, "Converter closed.");
+               return MEDIA_CONVERTER_ERROR;
+       }
+       
+       //printf ("converting...\n");
+
+       // There seems to be no documentation about what
+       // sws_scale's return value means.
+       sws_scale (scaler, src, srcStride, srcSlideY, srcSlideH, dest, 
dstStride);
+       
+       return MEDIA_SUCCESS;
+}
+
+
+/*
+ * FfmpegConverterInfo
+ */
+
+bool
+FfmpegConverterInfo::Supports (MoonPixelFormat input, MoonPixelFormat output)
+{
+       return FfmpegConverter::ToFfmpegPixFmt (input)  != PIX_FMT_NONE 
+               && FfmpegConverter::ToFfmpegPixFmt (output) != PIX_FMT_NONE;
+}
+
+IImageConverter*
+FfmpegConverterInfo::Create (Media* media, VideoStream* stream)
+{
+       return new FfmpegConverter (media, stream);
+}
+
 #endif // INCLUDE_FFMPEG
 

Modified: trunk/moon/src/pipeline-ffmpeg.h
===================================================================
--- trunk/moon/src/pipeline-ffmpeg.h    2008-01-11 14:48:10 UTC (rev 92669)
+++ trunk/moon/src/pipeline-ffmpeg.h    2008-01-11 14:50:22 UTC (rev 92670)
@@ -9,7 +9,12 @@
  * See the LICENSE file included with the distribution for details.
  * 
  */
- 
+
+#ifdef INCLUDE_FFMPEG
+
+#ifndef __MOON_PIPELINE_FFMPEG__
+#define __MOON_PIPELINE_FFMPEG__
+
 #include <glib.h>
 #include <unistd.h>
 
@@ -25,6 +30,8 @@
  
 #define AUDIO_BUFFER_SIZE (AVCODEC_MAX_AUDIO_FRAME_SIZE * 2)
  
+void register_ffmpeg ();
+
 class FfmpegDemuxer : public IMediaDemuxer {
 public:
        FfmpegDemuxer (Media* media) : IMediaDemuxer (media) {}
@@ -37,98 +44,42 @@
        
        virtual MediaResult DecodeFrame (MediaFrame* frame);
        virtual MediaResult Open ();
+       virtual void Cleanup (MediaFrame* frame);
        
-       virtual void Cleanup (MediaFrame* frame)
-       {
-               AVFrame* av_frame = (AVFrame*) frame->decoder_specific_data;
-               if (av_frame != NULL) {
-                       av_free (av_frame);
-                       frame->decoder_specific_data = NULL;
-               }
-       }
-       
 private:
        AVCodecContext *context;
        uint8_t* audio_buffer;
 };
 
+class FfmpegDecoderInfo : public DecoderInfo {
+public:
+       virtual bool Supports (const char* codec);
+       virtual IMediaDecoder* Create (Media* media, IMediaStream* stream);
+       virtual const char* GetName () { return "FfmpegDecoder"; }
+};
+
 class FfmpegConverter : public IImageConverter {
 public:
-       FfmpegConverter (Media* media, VideoStream* stream) : IImageConverter 
(media, stream)
-       {
-               scaler = NULL;
-       }
+       FfmpegConverter (Media* media, VideoStream* stream);    
+       ~FfmpegConverter ();
        
-       ~FfmpegConverter ()
-       {
-               if (scaler != NULL) {
-                       sws_freeContext (scaler);
-                       scaler = NULL;
-               }
-       }
+       MediaResult Open ();
+       MediaResult Convert (uint8_t *src[], int srcStride[], int srcSlideY, 
int srcSlideH, uint8_t* dest[], int dstStride []);
        
-       static PixelFormat ToFfmpegPixFmt (MoonPixelFormat format)
-       {
-               switch (format) {
-               case MoonPixelFormatYUV420P: return PIX_FMT_YUV420P;  
-               case MoonPixelFormatRGB32: return PIX_FMT_RGB32;
-               default:
-                       printf ("FfmpegConverter::ToFfmpegPixFmt (%i): Unknown 
pixel format.\n", format);
-                       return PIX_FMT_NONE;
-               }
-       }
+       static PixelFormat ToFfmpegPixFmt (MoonPixelFormat format);     
+       static MoonPixelFormat ToMoonPixFmt (PixelFormat format);
        
-       static MoonPixelFormat ToMoonPixFmt (PixelFormat format)
-       {
-               switch (format) {
-               case PIX_FMT_YUV420P: return MoonPixelFormatYUV420P;
-               case PIX_FMT_RGB32: return MoonPixelFormatRGB32;
-               default:
-                       printf ("FfmpegConverter::ToMoonPixFmt (%i): Unknown 
pixel format.\n", format);
-                       return MoonPixelFormatNone;
-               };
-       }
-       
-       MediaResult Open ()
-       {
-               PixelFormat in_format = ToFfmpegPixFmt (input_format);
-               PixelFormat out_format = ToFfmpegPixFmt (output_format);
-               
-               if (in_format == PIX_FMT_NONE) {
-                       media->AddMessage (MEDIA_CONVERTER_ERROR, "Invalid 
input format.");
-                       return MEDIA_CONVERTER_ERROR;
-               }
-               
-               if (out_format == PIX_FMT_NONE) {
-                       media->AddMessage (MEDIA_CONVERTER_ERROR, "Invalid 
output format.");
-                       return MEDIA_CONVERTER_ERROR;
-               }
-               
-               scaler = sws_getContext (stream->width, stream->height, 
in_format,
-                               stream->width, stream->height, out_format,
-                               SWS_BICUBIC, NULL, NULL, NULL);
-                               
-               return MEDIA_SUCCESS;
-       }
-       
-       MediaResult Convert (uint8_t *src[], int srcStride[], int srcSlideY, 
int srcSlideH, uint8_t* dest[], int dstStride [])
-       {
-               if (scaler == NULL) {
-                       media->AddMessage (MEDIA_CONVERTER_ERROR, "Converter 
closed.");
-                       return MEDIA_CONVERTER_ERROR;
-               }
-               
-               //printf ("converting...\n");
-       
-               // There seems to be no documentation about what
-               // sws_scale's return value means.
-               sws_scale (scaler, src, srcStride, srcSlideY, srcSlideH, dest, 
dstStride);
-               
-               return MEDIA_SUCCESS;
-       }
-       
 private:
        struct SwsContext *scaler;
 };
 
 
+class FfmpegConverterInfo : public ConverterInfo {
+public:
+       virtual bool Supports (MoonPixelFormat input, MoonPixelFormat output);
+       virtual IImageConverter* Create (Media* media, VideoStream* stream);
+       virtual const char* GetName () { return "FfmpegConverter"; }
+};
+
+#endif // __MOON_PIPELINE_FFMPEG__
+#endif // INCLUDE_FFMPEG

Modified: trunk/moon/src/pipeline.cpp
===================================================================
--- trunk/moon/src/pipeline.cpp 2008-01-11 14:48:10 UTC (rev 92669)
+++ trunk/moon/src/pipeline.cpp 2008-01-11 14:50:22 UTC (rev 92670)
@@ -27,21 +27,24 @@
 #define CODEC_MP3      0x55
 #define CODEC_WMAV1 0x160
 #define CODEC_WMAV2 0x161
-                                       
+
+/*
+ * Media 
+ */
+DemuxerInfo* Media::registered_demuxers = NULL;
+DecoderInfo* Media::registered_decoders = NULL;
+ConverterInfo* Media::registered_converters = NULL;
+ 
 Media::Media (void* el) :
                source (NULL), demuxer (NULL), element (NULL),
                file_or_url (NULL), queued_requests (NULL),
                queue_closure (NULL)
 {
-       //if (element)
-       //      element->ref ();
 }
 
 Media::~Media ()
 {
        DeleteQueue ();
-       //if (element)
-       //      element->unref ();
                
        element = NULL;
        delete source;
@@ -56,6 +59,95 @@
 }
 
 void
+Media::RegisterDemuxer (DemuxerInfo* info)
+{
+       printf ("Media::RegisterDecoder (%p)\n", info);
+       info->next = NULL;
+       if (registered_demuxers == NULL) {
+               registered_demuxers = info;
+       } else {
+               MediaInfo* current = registered_demuxers;
+               while (current->next != NULL)
+                       current = current->next;
+               current->next = info;
+       }
+}
+
+void
+Media::RegisterConverter (ConverterInfo* info)
+{
+       printf ("Media::RegisterDecoder (%p)\n", info);
+       info->next = NULL;
+       if (registered_converters == NULL) {
+               registered_converters = info;
+       } else {
+               MediaInfo* current = registered_converters;
+               while (current->next != NULL)
+                       current = current->next;
+               current->next = info;
+       }
+}
+
+void
+Media::RegisterDecoder (DecoderInfo* info)
+{
+       printf ("Media::RegisterDecoder (%p)\n", info);
+       info->next = NULL;
+       if (registered_decoders == NULL) {
+               registered_decoders = info;
+       } else {
+               MediaInfo* current = registered_decoders;
+               while (current->next != NULL)
+                       current = current->next;
+               current->next = info;
+       }
+}
+
+void
+Media::Initialize ()
+{
+       // register stuff
+       Media::RegisterDemuxer (new ASFDemuxerInfo ());
+#ifdef INCLUDE_FFMPEG
+       register_ffmpeg ();
+#endif
+}
+
+void
+Media::Shutdown ()
+{
+       MediaInfo* current;
+       MediaInfo* next;
+       
+       current = registered_decoders;
+       while (current != NULL) {
+               next = current->next;
+               delete current;
+               current = next;
+       }
+       registered_decoders = NULL;
+       
+       current = registered_demuxers;
+       while (current != NULL) {
+               next = current->next;
+               delete current;
+               current = next;
+       }
+       registered_demuxers = NULL;
+       
+       
+       current = registered_converters;
+       while (current != NULL) {
+               next = current->next;
+               delete current;
+               current = next;
+       }
+       registered_converters = NULL;
+       
+       
+}
+
+void
 Media::AddMessage (MediaResult result, const char* msg)
 {
        printf ("Media::AddMessage (%i, '%s').\n", result, msg);
@@ -141,15 +233,33 @@
 {
        printf ("Media::Open ().\n");
        
-       MediaResult result = MEDIA_FAIL;
+       MediaResult result = MEDIA_FAIL; // We return success if at least 1 
stream could be opened correctly (has decoder and, if applicable, converter)
 
        if (source == NULL) {
-               return MediaResult (MEDIA_INVALID_ARGUMENT);
+               return MEDIA_INVALID_ARGUMENT;
        }
        
-       // Determine the container format
-       // Hard-code our own demuxer for the moment.
-       demuxer = new ASFDemuxer (this);
+       // Select a demuxer
+       uint8_t buffer [16];
+       if (!source->Peek (&buffer [0], 16)) {
+               return MEDIA_FAIL;
+       }
+       
+       DemuxerInfo* current_demuxer = registered_demuxers;
+       while (current_demuxer != NULL && !current_demuxer->Supports (&buffer 
[0], 16)) {
+               printf ("Checking registered demuxer '%s' if it supports the 
media file '%s': no.\n", current_demuxer->GetName (), file_or_url);
+               current_demuxer = (DemuxerInfo*) current_demuxer->next;
+       }
+               
+       if (current_demuxer == NULL) {
+               AddMessage (MEDIA_UNKNOWN_MEDIA_TYPE, g_strdup_printf ("No 
demuxers registered to handle the media file '%s'.", file_or_url));
+               return MEDIA_UNKNOWN_MEDIA_TYPE;
+       } else {
+               printf ("Checking registered demuxer '%s' if it supports the 
media file '%s': yes.\n", current_demuxer->GetName (), file_or_url);
+               demuxer = current_demuxer->Create (this);
+       }
+       
+       // Found a demuxer
        result = demuxer->ReadHeader ();
        
        if (!MEDIA_SUCCEEDED (result)) {
@@ -160,6 +270,8 @@
        
        printf ("Media::Open (): Starting to select codecs...\n");
        
+       result = MEDIA_FAIL; // Only set to SUCCESS if at least 1 stream can be 
used
+       
        // Select codecs for each stream
        for (int i = 0; i < demuxer->GetStreamCount (); i++) {
                IMediaStream* stream = demuxer->GetStream (i);
@@ -169,52 +281,70 @@
                const char* codec = stream->GetCodec ();
                IMediaDecoder* decoder = NULL;
                
-               printf ("Media::Open (%p): Selecting codec for codec %s, id 
%i.\n", source, codec, stream->codec_id);
-                               
-               if (decoder == NULL) {
-                       if (strcmp (codec, "wmv") == 0
-                               || strcmp (codec, "wma") == 0
-                               || strcmp (codec, "mp3") == 0
-                               || strcmp (codec, "vc1") == 0
-                               || strcmp (codec, "wmav2") == 0 
-                               ) {
-                               decoder = new FfmpegDecoder (this, stream);
-                       } else if (strcmp (codec, "ASFMARKER") == 0) {
-                               decoder = new ASFMarkerDecoder (this, stream);
-                       } else {
-                               AddMessage (MEDIA_UNKNOWN_CODEC, 
g_strdup_printf ("Unknown codec: '%s'", codec));
-                       }
+               printf ("Media::Open (): Selecting codec for codec %s, id 
%i.\n", codec, stream->codec_id);
+               
+               DecoderInfo* current_decoder = registered_decoders;
+               while (current_decoder != NULL && !current_decoder->Supports 
(codec)) {
+                       printf ("Checking registered decoder '%s' if it 
supports codec '%s': no.\n", current_decoder->GetName (), codec);
+                       current_decoder = (DecoderInfo*) current_decoder->next;
                }
-               
+
+               if (current_decoder == NULL) {
+                       AddMessage (MEDIA_UNKNOWN_CODEC, g_strdup_printf 
("Unknown codec: '%s'.", codec));      
+               } else {
+                       printf ("Checking registered decoder '%s' if it 
supports codec '%s': yes.\n", current_decoder->GetName (), codec);
+                       decoder = current_decoder->Create (this, stream);
+               }
+
                if (decoder != NULL) {
                        result = decoder->Open ();
                        if (!MEDIA_SUCCEEDED (result)) {
                                delete decoder;
                                decoder = NULL;
                        }
+               }
                
-               
                if (decoder != NULL) {
-                       stream->SetDecoder (decoder);
-                       
-                       if (stream->GetType () == MediaTypeVideo) {
+                       // Select converter for this stream
+                       if (stream->GetType () == MediaTypeVideo && 
decoder->pixel_format != MoonPixelFormatRGB32) {
                                VideoStream* vs = (VideoStream*) stream;
                                IImageConverter* converter;
-                               converter = new FfmpegConverter (this, vs);
-                               converter->input_format = 
vs->decoder->pixel_format;
-                               converter->output_format = MoonPixelFormatRGB32;
-                               if (MEDIA_SUCCEEDED (converter->Open ())) {
-                                       // FIXME: What should happen if there's 
no available converter? No video?
+                               
+                               ConverterInfo* current_conv = 
registered_converters;
+                               while (current_conv != NULL && 
!current_conv->Supports (decoder->pixel_format, MoonPixelFormatRGB32)) {
+                                       printf ("Checking registered converter 
'%s' if it supports input '%i' and output '%i': no.\n", current_conv->GetName 
(), decoder->pixel_format, MoonPixelFormatRGB32);
+                                       current_conv = (ConverterInfo*) 
current_conv->next;
+                               }
+
+                               if (current_conv == NULL) {
+                                       AddMessage (MEDIA_UNKNOWN_CONVERTER, 
g_strdup_printf ("Can't convert from %i to %i: No converter found.", 
vs->decoder->pixel_format, MoonPixelFormatRGB32));    
+                               } else {
+                                       printf ("Checking registered converter 
'%s' if it supports input '%i' and output '%i': yes.\n", current_conv->GetName 
(), decoder->pixel_format, MoonPixelFormatRGB32);
+                                       converter = current_conv->Create (this, 
vs);
+                                       converter->input_format = 
decoder->pixel_format;
+                                       converter->output_format = 
MoonPixelFormatRGB32;
+                                       if (!MEDIA_SUCCEEDED (converter->Open 
())) {
+                                               delete converter;
+                                               converter = NULL;
+                                       }
+                               }
+
+                               if (converter != NULL) {                        
        
                                        vs->converter = converter;
                                } else {
-                                       delete converter;
-                                       converter = NULL;
+                                       delete decoder;
+                                       decoder = NULL;
                                }
                        }
-               }}
+               }
+               
+               if (decoder != NULL) {
+                       stream->SetDecoder (decoder);
+                       result = MEDIA_SUCCESS;
+               }
        }
        
-       return MEDIA_SUCCESS;
+       return result;
 }
 
 MediaFrame*
@@ -602,6 +732,29 @@
 }
 
 /*
+ * ASFDemuxerInfo
+ */
+
+bool
+ASFDemuxerInfo::Supports (uint8_t* buffer, uint32_t length)
+{
+       if (length < 16)
+               return false;
+               
+       bool result = asf_guid_compare (&asf_guids_header, (asf_guid*) buffer);
+
+       printf ("ASFDemuxerInfo::Supports (%p, %u): probing result: %s\n", 
buffer, length, result ? "true" : "false");
+       
+       return result;
+}
+
+IMediaDemuxer*
+ASFDemuxerInfo::Create (Media* media)
+{
+       return new ASFDemuxer (media);
+} 
+
+/*
  *     FileSource
  */
 
@@ -672,9 +825,11 @@
 bool
 FileSource::Peek (void* buffer, guint32 size)
 {
-       printf ("FileSource::Seek (%p, %u).\n", buffer, size);
-       printf ("FileSource::Peek (%p, %u): Not implemented.\n", buffer, size);
-       return false;
+       // Simple implementation of peek: save position, read bytes, restore 
position.
+       gint64 position = GetPosition ();
+       if (!Read (buffer, size))
+               return false;
+       return Seek (position, SEEK_SET);
 }
 
 guint64
@@ -693,22 +848,24 @@
 }
 
 bool
-FileSource::Seek (gint64 position)
+FileSource::Seek (gint64 offset)
 {
        //printf ("FileSource::Seek (%llu).\n", position);
        
-       return Seek (position, SEEK_CUR);
+       return Seek (offset, SEEK_CUR);
 }
 
 bool
-FileSource::Seek (gint64 position, int mode)
+FileSource::Seek (gint64 offset, int mode)
 {
-       //printf ("FileSource::Seek (%llu, %i).\n", position, mode);
+       printf ("FileSource::Seek (%llu, %i).\n", offset, mode);
        
-       if (fseek (fd, position, mode) != 0) {
-               media->AddMessage (MEDIA_SEEK_ERROR, g_strdup_printf ("Can't 
seek to offset %llu with mode %i in '%s': %s.\n", position, mode,  filename, 
strerror (errno)));
+       int result = fseek (fd, offset, mode);
+       if (result != 0) {
+               media->AddMessage (MEDIA_SEEK_ERROR, g_strdup_printf ("Can't 
seek to offset %llu with mode %i in '%s': %s.\n", offset, mode, filename, 
strerror (errno)));
                return false;
        }
+       printf  ("fseek returned: %i, position: %llu\n", result, GetPosition 
());
        return true;
 }
 
@@ -797,7 +954,11 @@
        uncompressed_data = NULL;
        
        if (decoder_specific_data != NULL) {
-               stream->decoder->Cleanup (this);
+               if (stream != NULL && stream->decoder != NULL) { 
+                       stream->decoder->Cleanup (this);
+               } else {
+                       printf ("MediaFrame::~MediaFrame (): Couldn't call 
decoder->Cleanup.\n");
+               }
        }
 }
 

Modified: trunk/moon/src/pipeline.h
===================================================================
--- trunk/moon/src/pipeline.h   2008-01-11 14:48:10 UTC (rev 92669)
+++ trunk/moon/src/pipeline.h   2008-01-11 14:50:22 UTC (rev 92670)
@@ -111,6 +111,8 @@
 #define MEDIA_OUT_OF_MEMORY ((MediaResult) 10)
 #define MEDIA_DEMUXER_ERROR ((MediaResult) 11)
 #define MEDIA_CONVERTER_ERROR ((MediaResult) 12)
+#define MEDIA_UNKNOWN_CONVERTER ((MediaResult) 13)
+#define MEDIA_UNKNOWN_MEDIA_TYPE ((MediaResult) 14)
 
 #define MEDIA_SUCCEEDED(x) ((x == 0))
 
@@ -144,6 +146,38 @@
        MediaResult Call ();
 }; 
 
+/*
+ * *Info classes used to register codecs, demuxers and converters.
+ */
+
+class MediaInfo {
+public:
+       MediaInfo* next; // Used internally by Media.
+       MediaInfo () : next (NULL) {}
+       virtual ~MediaInfo () {}
+       virtual const char* GetName () { return "Unknown"; }
+};
+
+class DecoderInfo : public MediaInfo {
+public:
+       virtual bool Supports (const char* codec) = 0;
+       virtual IMediaDecoder* Create (Media* media, IMediaStream* stream) = 0;
+};
+
+class DemuxerInfo : public MediaInfo  {
+public:
+       // <buffer> points to the first <length> bytes of a file. 
+       // <length> is guaranteed to be at least 16 bytes.
+       virtual bool Supports (uint8_t* buffer, uint32_t length) = 0; 
+       virtual IMediaDemuxer* Create (Media* media) = 0;
+};
+
+class ConverterInfo : public MediaInfo  {
+public:
+       virtual bool Supports (MoonPixelFormat input, MoonPixelFormat output) = 
0;
+       virtual IImageConverter* Create (Media* media, VideoStream* stream) = 0;
+};
+
 class Media {
 public:
        Media (void* element);
@@ -193,7 +227,22 @@
     void AddMessage (MediaResult result, const char* msg);
     void AddMessage (MediaResult result, char* msg);
     
+    
+public:
+    // Registration functions
+    // This class takes ownership of the infos and will delete them (not free) 
when the Media is shutdown.
+    static void RegisterDemuxer (DemuxerInfo *info);
+    static void RegisterDecoder (DecoderInfo *info);
+    static void RegisterConverter (ConverterInfo *info);
+
+       static void Initialize ();
+       static void Shutdown ();
 private:
+       static DemuxerInfo* registered_demuxers;
+       static DecoderInfo* registered_decoders;
+       static ConverterInfo* registered_converters;
+    
+private:
        //      Called on another thread, loops the queue of requested frames 
        //      and calls GetNextFrame and FrameReadCallback.
        //      If there are any requests for audio frames in the queue
@@ -310,11 +359,12 @@
        IMediaSource (Media* med) : media (med) {}
        virtual ~IMediaSource () {}
        virtual bool IsSeekable () = 0;
-       virtual bool Seek (gint64 position) = 0;
-       virtual bool Seek (gint64 position, int mode) = 0;
+       virtual bool Seek (gint64 offset) = 0; // Seeks to the offset from the 
current position
+       virtual bool Seek (gint64 offset, int mode) = 0;
        virtual bool Read (void* buffer, guint32 size) = 0;
        virtual bool Peek (void* buffer, guint32 size) = 0;
        virtual guint64 GetPosition () = 0;
+       virtual void SetPosition (guint64 position) { Seek (position, 
SEEK_SET); }
        virtual bool Eof () = 0;
        
 protected:
@@ -467,6 +517,13 @@
        gint32* stream_to_asf_index;
 };
 
+class ASFDemuxerInfo : public DemuxerInfo {
+public:
+       virtual bool Supports (uint8_t* buffer, uint32_t length); 
+       virtual IMediaDemuxer* Create (Media* media); 
+       virtual const char* GetName () { return "ASFDemuxer"; }
+};
+
 class ASFMarkerStream : public IMediaStream {
 public:
        ASFMarkerStream (Media* media) : IMediaStream (media) {}

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to