* configure.ac.in, modules/codec/Modules.am, modules/codec/libmpeg2.c:
authorGildas Bazin <gbazin@videolan.org>
Tue, 25 Feb 2003 17:15:32 +0000 (17:15 +0000)
committerGildas Bazin <gbazin@videolan.org>
Tue, 25 Feb 2003 17:15:32 +0000 (17:15 +0000)
   Added a simple mpeg video decoder based on libmpeg2. It is mainly useful
   for comparing the performance against our custom decoder as it is currently
   missing some important features like the synchro stuff.

configure.ac.in
modules/codec/Modules.am
modules/codec/libmpeg2.c [new file with mode: 0755]

index fbfb40d..b47f818 100644 (file)
@@ -171,7 +171,7 @@ dnl
 dnl Gettext stuff
 dnl
 ALL_LINGUAS="de en_GB fr it ja no ru nl pl sv"
-AM_GNU_GETTEXT_VERSION(0.10.40)
+AM_GNU_GETTEXT_VERSION(0.11.5)
 AM_GNU_GETTEXT
 if test "${nls_cv_force_use_gnu_gettext}" = "yes"; then
   AC_DEFINE(HAVE_INCLUDED_GETTEXT, 1, Define if we use the local libintl)
@@ -1756,7 +1756,7 @@ dnl
 dnl  Flac plugin
 dnl
 AC_ARG_ENABLE(flac,
-  [  --enable-falc         flac decoder support (default disabled)])
+  [  --enable-flac           flac decoder support (default disabled)])
 if test "x${enable_flac}" = "xyes"
 then
   AC_CHECK_HEADERS(FLAC/stream_decoder.h, [
@@ -1765,6 +1765,19 @@ then
    ],[])
 fi
 
+dnl
+dnl  Libmpeg2 plugin
+dnl
+AC_ARG_ENABLE(libmpeg2,
+  [  --enable-libmpeg2       libmpeg2 decoder support (default disabled)])
+if test "x${enable_libmpeg2}" = "xyes"
+then
+  AC_CHECK_HEADERS(mpeg2dec/mpeg2.h, [
+    PLUGINS="${PLUGINS} libmpeg2"
+    LDFLAGS_libmpeg2="${LDFLAGS_libmpeg2} -lmpeg2"
+   ],[])
+fi
+
 dnl
 dnl  Vorbis plugin
 dnl
index 701a4a2..5fc3618 100644 (file)
@@ -10,3 +10,4 @@ SOURCES_dv = modules/codec/dv.c
 SOURCES_xvid = modules/codec/xvid.c
 SOURCES_adpcm = modules/codec/adpcm.c
 SOURCES_mpeg_audio = modules/codec/mpeg_audio.c
+SOURCES_libmpeg2 = modules/codec/libmpeg2.c
diff --git a/modules/codec/libmpeg2.c b/modules/codec/libmpeg2.c
new file mode 100755 (executable)
index 0000000..cf67490
--- /dev/null
@@ -0,0 +1,283 @@
+/*****************************************************************************\r
+ * libmpeg2.c: mpeg2 video decoder module making use of libmpeg2.\r
+ *****************************************************************************\r
+ * Copyright (C) 1999-2001 VideoLAN\r
+ * $Id: libmpeg2.c,v 1.1 2003/02/25 17:15:32 gbazin Exp $\r
+ *\r
+ * Authors: Gildas Bazin <gbazin@netcourrier.com>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.\r
+ *****************************************************************************/\r
+\r
+/*****************************************************************************\r
+ * Preamble\r
+ *****************************************************************************/\r
+#include <vlc/vlc.h>\r
+#include <vlc/vout.h>\r
+#include <vlc/input.h>\r
+#include <vlc/decoder.h>\r
+\r
+#include <stdlib.h>                                      /* malloc(), free() */\r
+#include <string.h>                                    /* memcpy(), memset() */\r
+\r
+#include <mpeg2dec/mpeg2.h>\r
+\r
+/*****************************************************************************\r
+ * dec_thread_t : libmpeg2 decoder thread descriptor\r
+ *****************************************************************************/\r
+typedef struct dec_thread_t\r
+{\r
+    /*\r
+     * libmpeg2 properties\r
+     */\r
+    mpeg2dec_t          *p_mpeg2dec;\r
+    const mpeg2_info_t  *p_info;\r
+\r
+    /*\r
+     * Input properties\r
+     */\r
+    decoder_fifo_t   *p_fifo;                  /* stores the PES stream data */\r
+    pes_packet_t     *p_pes;                  /* current PES we are decoding */\r
+    mtime_t          i_pts;\r
+\r
+    /*\r
+     * Output properties\r
+     */\r
+    vout_thread_t *p_vout;\r
+\r
+} dec_thread_t;\r
+\r
+/*****************************************************************************\r
+ * Local prototypes\r
+ *****************************************************************************/\r
+static int  OpenDecoder  ( vlc_object_t * );\r
+static int  RunDecoder   ( decoder_fifo_t * );\r
+static void CloseDecoder ( dec_thread_t * );\r
+\r
+/*****************************************************************************\r
+ * Module descriptor\r
+ *****************************************************************************/\r
+vlc_module_begin();\r
+    set_description( _("libmpeg2 decoder module") );\r
+    set_capability( "decoder", 40 );\r
+    set_callbacks( OpenDecoder, NULL );\r
+    add_shortcut( "libmpeg2" );\r
+vlc_module_end();\r
+\r
+/*****************************************************************************\r
+ * OpenDecoder: probe the decoder and return score\r
+ *****************************************************************************/\r
+static int OpenDecoder( vlc_object_t *p_this )\r
+{\r
+    decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;\r
+\r
+    if( p_fifo->i_fourcc != VLC_FOURCC('m','p','g','v') )\r
+    {\r
+        return VLC_EGENERIC;\r
+    }\r
+\r
+    p_fifo->pf_run = RunDecoder;\r
+    return VLC_SUCCESS;\r
+}\r
+/*****************************************************************************\r
+ * RunDecoder: the libmpeg2 decoder\r
+ *****************************************************************************/\r
+static int RunDecoder( decoder_fifo_t *p_fifo )\r
+{\r
+    dec_thread_t    *p_dec;\r
+    data_packet_t   *p_data = NULL;\r
+    mpeg2_state_t   state;\r
+    picture_t       *p_pic;\r
+    int             i_aspect, i_chroma;\r
+\r
+    /* Allocate the memory needed to store the thread's structure */\r
+    if( (p_dec = (dec_thread_t *)malloc (sizeof(dec_thread_t)) )\r
+        == NULL)\r
+    {\r
+        msg_Err( p_fifo, "out of memory" );\r
+        goto error;\r
+    }\r
+\r
+    /* Initialize the thread properties */\r
+    memset( p_dec, 0, sizeof(dec_thread_t) );\r
+    p_dec->p_fifo     = p_fifo;\r
+    p_dec->p_pes      = NULL;\r
+    p_dec->p_vout     = NULL;\r
+    p_dec->p_mpeg2dec = NULL;\r
+    p_dec->p_info     = NULL;\r
+    p_dec->i_pts      = 0;\r
+\r
+    /* Initialize decoder */\r
+    p_dec->p_mpeg2dec = mpeg2_init();\r
+    if( p_dec->p_mpeg2dec == NULL)\r
+        goto error;\r
+\r
+    p_dec->p_info = mpeg2_info( p_dec->p_mpeg2dec );\r
+\r
+    /* libmpeg2 decoder thread's main loop */\r
+    while( (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error) )\r
+    {\r
+        state = mpeg2_parse( p_dec->p_mpeg2dec );\r
+\r
+        switch( state )\r
+        {\r
+        case STATE_BUFFER:\r
+            /* Feed libmpeg2 a data packet at a time */\r
+            if( p_data == NULL )\r
+            {\r
+                /* Get the next PES */\r
+                if( p_dec->p_pes )\r
+                    input_DeletePES( p_dec->p_fifo->p_packets_mgt,\r
+                                     p_dec->p_pes );\r
+\r
+                input_ExtractPES( p_dec->p_fifo, &p_dec->p_pes );\r
+                if( !p_dec->p_pes )\r
+                {\r
+                    p_dec->p_fifo->b_error = 1;\r
+                    break;\r
+                }\r
+\r
+                if( p_dec->p_pes->i_pts )\r
+                {\r
+                    mpeg2_pts( p_dec->p_mpeg2dec,\r
+                               p_dec->p_pes->i_pts * 9 / 100 );\r
+                }\r
+                p_data = p_dec->p_pes->p_first;\r
+            }\r
+\r
+            if( p_data != NULL )\r
+            {\r
+                mpeg2_buffer( p_dec->p_mpeg2dec,\r
+                              p_data->p_payload_start,\r
+                              p_data->p_payload_end );\r
+\r
+                p_data = p_data->p_next;\r
+            }\r
+            break;\r
+\r
+        case STATE_SEQUENCE:\r
+            /* Initialize video output */\r
+            i_aspect = p_dec->p_info->sequence->width *\r
+                p_dec->p_info->sequence->pixel_width /\r
+                p_dec->p_info->sequence->height * VOUT_ASPECT_FACTOR /\r
+                p_dec->p_info->sequence->pixel_height;\r
+\r
+            i_chroma = VLC_FOURCC('Y','V','1','2');\r
+\r
+            p_dec->p_vout = vout_Request( p_dec->p_fifo, p_dec->p_vout,\r
+                                          p_dec->p_info->sequence->width,\r
+                                          p_dec->p_info->sequence->height,\r
+                                          i_chroma, i_aspect );\r
+            break;\r
+\r
+        case STATE_PICTURE:\r
+          {\r
+            uint8_t * buf[3];\r
+\r
+            /* Get a new picture */\r
+            while( !(p_pic = vout_CreatePicture( p_dec->p_vout, 0, 0, 0 ) ) )\r
+            {\r
+                if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )\r
+                    break;\r
+\r
+                msleep( VOUT_OUTMEM_SLEEP );\r
+            }\r
+            if( p_pic == NULL )\r
+                break;\r
+\r
+            buf[0] = p_pic->p[0].p_pixels;\r
+            buf[1] = p_pic->p[1].p_pixels;\r
+            buf[2] = p_pic->p[2].p_pixels;\r
+            mpeg2_set_buf( p_dec->p_mpeg2dec, buf, p_pic );\r
+          }\r
+          break;\r
+\r
+        case STATE_END:\r
+            msg_Err( p_dec->p_fifo, "STATE_END" );\r
+        case STATE_SLICE:\r
+#if 0\r
+            msg_Err( p_dec->p_fifo, "STATE_SLICE: %i",\r
+                     p_dec->p_info->display_fbuf ?\r
+                     p_dec->p_info->display_fbuf->id : -1 );\r
+#endif\r
+            if( p_dec->p_info->display_fbuf\r
+                && p_dec->p_info->display_fbuf->id )\r
+            {\r
+                p_pic = (picture_t *)p_dec->p_info->display_fbuf->id;\r
+\r
+                if( p_dec->p_info->display_picture->flags & PIC_FLAG_PTS )\r
+                {\r
+                    p_dec->i_pts =\r
+                        ((mtime_t)p_dec->p_info->display_picture->pts)\r
+                        * 100 / 9;\r
+                }\r
+                else\r
+                {\r
+                    p_dec->i_pts += (p_dec->p_info->sequence->frame_period/27);\r
+                }\r
+\r
+                vout_DatePicture( p_dec->p_vout, p_pic, p_dec->i_pts );\r
+\r
+                vout_DisplayPicture( p_dec->p_vout, p_pic );\r
+            }\r
+            break;\r
+\r
+        default:\r
+            break;\r
+        }\r
+    }\r
+\r
+    /* If b_error is set, the libmpeg2 decoder thread enters the error loop */\r
+    if( p_dec->p_fifo->b_error )\r
+    {\r
+        DecoderError( p_dec->p_fifo );\r
+    }\r
+\r
+    /* End of the libmpeg2 decoder thread */\r
+    CloseDecoder( p_dec );\r
+\r
+    return 0;\r
+\r
+ error:\r
+    DecoderError( p_fifo );\r
+    if( p_dec )\r
+    {\r
+        if( p_dec->p_fifo )\r
+            p_dec->p_fifo->b_error = 1;\r
+\r
+        /* End of the libmpeg2 decoder thread */\r
+        CloseDecoder( p_dec );\r
+    }\r
+\r
+    return -1;\r
+}\r
+\r
+/*****************************************************************************\r
+ * CloseDecoder: libmpeg2 decoder destruction\r
+ *****************************************************************************/\r
+static void CloseDecoder( dec_thread_t * p_dec )\r
+{\r
+    if( p_dec )\r
+    {\r
+        if( p_dec->p_pes )\r
+            input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_dec->p_pes );\r
+\r
+        vout_Request( p_dec->p_fifo, p_dec->p_vout, 0, 0, 0, 0 );\r
+\r
+        if( p_dec->p_mpeg2dec ) mpeg2_close( p_dec->p_mpeg2dec );\r
+\r
+        free( p_dec );\r
+    }\r
+}\r