]> git.sesse.net Git - vlc/blobdiff - plugins/mpeg_vdec/vpar_headers.c
* ALL: the first libvlc commit.
[vlc] / plugins / mpeg_vdec / vpar_headers.c
index 9d197d19be405d4d7b5e8b66fb688c057af913f4..ac738402c4adc8c20d9ebb9ce9ae794df258aff3 100644 (file)
@@ -2,7 +2,7 @@
  * vpar_headers.c : headers parsing
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: vpar_headers.c,v 1.2 2001/11/28 15:08:05 massiot Exp $
+ * $Id: vpar_headers.c,v 1.23 2002/06/01 12:32:00 sam Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Stéphane Borel <stef@via.ecp.fr>
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
-#include "defs.h"
-
 #include <stdlib.h>                                                /* free() */
 #include <string.h>                                    /* memcpy(), memset() */
 
-#include "config.h"
-#include "common.h"
-#include "intf_msg.h"
-#include "threads.h"
-#include "mtime.h"
-
-#include "video.h"
-#include "video_output.h"
-
-#include "modules_export.h"
-#include "stream_control.h"
-#include "input_ext-dec.h"
-
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/decoder.h>
 
 #include "vdec_ext-plugins.h"
 #include "vpar_pool.h"
@@ -52,7 +40,7 @@
 /*
  * Local prototypes
  */
-static __inline__ void NextStartCode( bit_stream_t * );
+static inline void NextStartCode( bit_stream_t * );
 static void SequenceHeader( vpar_thread_t * p_vpar );
 static void GroupHeader( vpar_thread_t * p_vpar );
 static void PictureHeader( vpar_thread_t * p_vpar );
@@ -125,9 +113,8 @@ u8 pi_scan[2][64] ATTR_ALIGN(16) =
 /*****************************************************************************
  * ReferenceUpdate : Update the reference pointers when we have a new picture
  *****************************************************************************/
-static void __inline__ ReferenceUpdate( vpar_thread_t * p_vpar,
-                                        int i_coding_type,
-                                        picture_t * p_newref )
+static void inline ReferenceUpdate( vpar_thread_t * p_vpar,
+                                    int i_coding_type, picture_t * p_newref )
 {
     if( i_coding_type != B_CODING_TYPE )
     {
@@ -158,9 +145,8 @@ static void __inline__ ReferenceUpdate( vpar_thread_t * p_vpar,
  * ReferenceReplace : Replace the last reference pointer when we destroy
  *                    a picture
  *****************************************************************************/
-static void __inline__ ReferenceReplace( vpar_thread_t * p_vpar,
-                                         int i_coding_type,
-                                         picture_t * p_newref )
+static void inline ReferenceReplace( vpar_thread_t * p_vpar,
+                                     int i_coding_type, picture_t * p_newref )
 {
     if( i_coding_type != B_CODING_TYPE )
     {
@@ -179,8 +165,8 @@ static void __inline__ ReferenceReplace( vpar_thread_t * p_vpar,
 /*****************************************************************************
  * LoadMatrix : Load a quantization matrix
  *****************************************************************************/
-static __inline__ void LoadMatrix( vpar_thread_t * p_vpar,
-                                   quant_matrix_t * p_matrix )
+static inline void LoadMatrix( vpar_thread_t * p_vpar,
+                               quant_matrix_t * p_matrix )
 {
     int i_dummy;
 
@@ -189,7 +175,7 @@ static __inline__ void LoadMatrix( vpar_thread_t * p_vpar,
         /* Allocate a piece of memory to load the matrix. */
         if( (p_matrix->pi_matrix = (u8 *)malloc( 64*sizeof(u8) )) == NULL )
         {
-            intf_ErrMsg( "vpar error: allocation error in LoadMatrix()" );
+            msg_Err( p_vpar->p_fifo, "out of memory" );
             p_vpar->p_fifo->b_error = 1;
             return;
         }
@@ -206,7 +192,7 @@ static __inline__ void LoadMatrix( vpar_thread_t * p_vpar,
 /*****************************************************************************
  * LinkMatrix : Link a quantization matrix to another
  *****************************************************************************/
-static __inline__ void LinkMatrix( quant_matrix_t * p_matrix, u8 * pi_array )
+static inline void LinkMatrix( quant_matrix_t * p_matrix, u8 * pi_array )
 {
     if( p_matrix->b_allocated )
     {
@@ -218,6 +204,28 @@ static __inline__ void LinkMatrix( quant_matrix_t * p_matrix, u8 * pi_array )
     p_matrix->pi_matrix = pi_array;
 }
 
+/*****************************************************************************
+ * ChromaToFourCC: Return a FourCC value used by the video output.
+ *****************************************************************************/
+static inline u64 ChromaToFourCC( int i_chroma )
+{
+    switch( i_chroma )
+    {
+        case CHROMA_420:
+            return FOURCC_I420;
+
+        case CHROMA_422:
+            return FOURCC_I422;
+
+        case CHROMA_444:
+            return FOURCC_I444;
+
+        default:
+            /* This can't happen */
+            return 0xdeadbeef;
+    }
+}
+
 /*
  * Exported functions.
  */
@@ -244,36 +252,33 @@ int vpar_NextSequenceHeader( vpar_thread_t * p_vpar )
  *****************************************************************************/
 int vpar_ParseHeader( vpar_thread_t * p_vpar )
 {
-    while( !p_vpar->p_fifo->b_die )
+    NextStartCode( &p_vpar->bit_stream );
+    switch( GetBits32( &p_vpar->bit_stream ) )
     {
-        NextStartCode( &p_vpar->bit_stream );
-        switch( GetBits32( &p_vpar->bit_stream ) )
-        {
-        case SEQUENCE_HEADER_CODE:
-            p_vpar->c_sequences++;
-
-            SequenceHeader( p_vpar );
-            return 0;
-            break;
-
-        case GROUP_START_CODE:
-            GroupHeader( p_vpar );
-            return 0;
-            break;
+    case SEQUENCE_HEADER_CODE:
+        p_vpar->c_sequences++;
+        SequenceHeader( p_vpar );
+        return 0;
 
-        case PICTURE_START_CODE:
-            PictureHeader( p_vpar );
-            return 0;
-            break;
+    case GROUP_START_CODE:
+        GroupHeader( p_vpar );
+        return 0;
 
-        case SEQUENCE_END_CODE:
-            intf_DbgMsg("vpar debug: sequence end code received");
-            return 1;
-            break;
+    case PICTURE_START_CODE:
+        PictureHeader( p_vpar );
+        return 0;
 
-        default:
-            break;
+    case SEQUENCE_END_CODE:
+        msg_Dbg( p_vpar->p_fifo, "sequence end code received" );
+        if( p_vpar->sequence.p_backward != NULL )
+        {
+            p_vpar->sequence.p_backward->b_force = 1;
         }
+        ReferenceUpdate( p_vpar, I_CODING_TYPE, NULL );
+        return 1;
+
+    default:
+        break;
     }
 
     return 0;
@@ -304,14 +309,14 @@ static void SequenceHeader( vpar_thread_t * p_vpar )
     };
 #undef RESERVED
 
-    int i_height_save, i_width_save;
+    int i_height_save, i_width_save, i_aspect;
 
     i_height_save = p_vpar->sequence.i_height;
     i_width_save = p_vpar->sequence.i_width;
 
     p_vpar->sequence.i_width = GetBits( &p_vpar->bit_stream, 12 );
     p_vpar->sequence.i_height = GetBits( &p_vpar->bit_stream, 12 );
-    p_vpar->sequence.i_aspect_ratio = GetBits( &p_vpar->bit_stream, 4 );
+    i_aspect = GetBits( &p_vpar->bit_stream, 4 );
     p_vpar->sequence.i_frame_rate =
             i_frame_rate_table[ GetBits( &p_vpar->bit_stream, 4 ) ];
 
@@ -382,12 +387,64 @@ static void SequenceHeader( vpar_thread_t * p_vpar )
     else
     {
         /* It's an MPEG-1 stream. Put adequate parameters. */
+        int i_xyratio;
+        static int pi_mpeg1ratio[15] = {
+            10000, 10000,  6735,  7031,  7615,  8055,  8437, 8935,
+             9157,  9815, 10255, 10695, 10950, 11575, 12015
+        };
+
+        if( i_aspect > 1 )
+        {
+                i_xyratio = p_vpar->sequence.i_height *
+                        pi_mpeg1ratio[i_aspect] / p_vpar->sequence.i_width;
+                if( 7450 < i_xyratio && i_xyratio < 7550 )
+                {
+                        i_aspect = 2;
+                }
+                else if( 5575 < i_xyratio && i_xyratio < 5675 )
+                {
+                        i_aspect = 3;
+                }
+                else if( 4475 < i_xyratio && i_xyratio < 4575 )
+                {
+                        i_aspect = 4;
+                }
+        }
 
         p_vpar->sequence.b_mpeg2 = 0;
         p_vpar->sequence.b_progressive = 1;
         p_vpar->sequence.i_chroma_format = CHROMA_420;
     }
 
+    /* check whether the input gives a particular aspect ratio */
+    if( p_vpar->p_fifo->p_demux_data
+         && ( *(int*)(p_vpar->p_fifo->p_demux_data) & 0x7 ) )
+    {
+        i_aspect = *(int*)(p_vpar->p_fifo->p_demux_data);
+    }
+
+    /* Store calculated aspect ratio */
+    switch( i_aspect )
+    {
+        case AR_3_4_PICTURE:
+            p_vpar->sequence.i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
+            break;
+
+        case AR_16_9_PICTURE:
+            p_vpar->sequence.i_aspect = VOUT_ASPECT_FACTOR * 16 / 9;
+            break;
+
+        case AR_221_1_PICTURE:
+            p_vpar->sequence.i_aspect = VOUT_ASPECT_FACTOR * 221 / 100;
+            break;
+
+        case AR_SQUARE_PICTURE:
+        default:
+            p_vpar->sequence.i_aspect = VOUT_ASPECT_FACTOR
+                    * p_vpar->sequence.i_width / p_vpar->sequence.i_height;
+            break;
+    }
+
     /* Update sizes */
     p_vpar->sequence.i_mb_width = (p_vpar->sequence.i_width + 15) / 16;
     p_vpar->sequence.i_mb_height = (p_vpar->sequence.b_progressive) ?
@@ -429,38 +486,51 @@ static void SequenceHeader( vpar_thread_t * p_vpar )
     /* Extension and User data */
     ExtensionAndUserData( p_vpar );
 
-    /* XXX: The vout request and fifo opening will eventually be here */
-
     /* Spawn a video output if there is none */
-    vlc_mutex_lock( &p_vout_bank->lock );
+
+    p_vpar->p_vout = vlc_object_find( p_vpar->p_fifo->p_vlc, VLC_OBJECT_VOUT,
+                                                             FIND_CHILD );
     
-    if( p_vout_bank->i_count == 0 )
+    if( p_vpar->p_vout )
+    {
+        if( p_vpar->p_vout->render.i_width != p_vpar->sequence.i_width
+             || p_vpar->p_vout->render.i_height != p_vpar->sequence.i_height
+             || p_vpar->p_vout->render.i_chroma != ChromaToFourCC( p_vpar->sequence.i_chroma_format )
+             || p_vpar->p_vout->render.i_aspect != p_vpar->sequence.i_aspect )
+        {
+            /* We are not interested in this format, close this vout */
+            vlc_object_unlink_all( p_vpar->p_vout );
+            vlc_object_release( p_vpar->p_vout );
+            vout_DestroyThread( p_vpar->p_vout );
+            p_vpar->p_vout = NULL;
+        }
+        else
+        {
+            /* This video output is cool! Hijack it. */
+            vlc_object_unlink_all( p_vpar->p_vout );
+            vlc_object_attach( p_vpar->p_vout, p_vpar->p_fifo );
+            vlc_object_release( p_vpar->p_vout );
+        }
+    }
+
+    if( p_vpar->p_vout == NULL )
     {
-        intf_WarnMsg( 1, "vpar: no vout present, spawning one" );
+        msg_Dbg( p_vpar->p_fifo, "no vout present, spawning one" );
 
-        p_vpar->p_vout = vout_CreateThread( NULL, p_vpar->sequence.i_width,
-                                            p_vpar->sequence.i_height );
+        p_vpar->p_vout = vout_CreateThread( p_vpar->p_fifo->p_this,
+                           p_vpar->sequence.i_width,
+                           p_vpar->sequence.i_height,
+                           ChromaToFourCC( p_vpar->sequence.i_chroma_format ),
+                           p_vpar->sequence.i_aspect );
 
         /* Everything failed */
         if( p_vpar->p_vout == NULL )
         {
-            intf_ErrMsg( "vpar error: can't open vout, aborting" );
-            vlc_mutex_unlock( &p_vout_bank->lock );
-
-            /* XXX ! XXX ! XXX ! what to do here ? */
+            msg_Err( p_vpar->p_fifo, "cannot open vout, aborting" );
+            p_vpar->p_fifo->b_error = 1;
             return;
         }
-        
-        p_vout_bank->pp_vout[ p_vout_bank->i_count ] = p_vpar->p_vout;
-        p_vout_bank->i_count++;
-    }
-    else
-    {
-        /* Take the first video output FIXME: take the best one */
-        p_vpar->p_vout = p_vout_bank->pp_vout[ 0 ];
     }
-
-    vlc_mutex_unlock( &p_vout_bank->lock );
 }
 
 /*****************************************************************************
@@ -479,7 +549,11 @@ static void GroupHeader( vpar_thread_t * p_vpar )
 static void PictureHeader( vpar_thread_t * p_vpar )
 {
     int                 i_structure, i_previous_coding_type;
-    boolean_t           b_parsable = 0;
+    vlc_bool_t          b_parsable = 0;
+
+    /* Retrieve the PTS. */
+    CurrentPTS( &p_vpar->bit_stream, &p_vpar->sequence.next_pts,
+                &p_vpar->sequence.next_dts );
 
     /* Recover in case of stream discontinuity. */
     if( p_vpar->sequence.b_expect_discontinuity )
@@ -599,7 +673,7 @@ static void PictureHeader( vpar_thread_t * p_vpar )
 
             p_vpar->picture.i_current_structure = 0;
 
-            intf_WarnMsg( 2, "Odd number of field pictures." );
+            msg_Warn( p_vpar->p_fifo, "odd number of field pictures" );
         }
         else
         {
@@ -641,7 +715,7 @@ static void PictureHeader( vpar_thread_t * p_vpar )
                      * but will prevent us from segfaulting in the slice
                      * parsing. */
                     static picture_t    fake_picture;
-                    fake_picture.p_data = NULL; /* We will use it later */
+                    fake_picture.i_planes = 0; /* We will use it later */
                     p_vpar->sequence.p_forward = &fake_picture;
                 }
             }
@@ -735,28 +809,21 @@ static void PictureHeader( vpar_thread_t * p_vpar )
     {
         /* This is a new frame. Get a structure from the video_output. */
         while( ( P_picture = vout_CreatePicture( p_vpar->p_vout,
-                              /* XXX */ 99+p_vpar->sequence.i_chroma_format,
-                                        p_vpar->sequence.i_width,
-                                        p_vpar->sequence.i_height ) )
-             == NULL )
+                                 p_vpar->picture.b_progressive,
+                                 p_vpar->picture.b_top_field_first,
+                                 p_vpar->picture.b_repeat_first_field ) )
+                 == NULL )
         {
-            intf_DbgMsg("vpar debug: allocation error in vout_CreatePicture, delaying");
             if( p_vpar->p_fifo->b_die || p_vpar->p_fifo->b_error )
             {
                 return;
             }
-            msleep( VPAR_OUTMEM_SLEEP );
+            msleep( VOUT_OUTMEM_SLEEP );
         }
 
         /* Initialize values. */
         vpar_SynchroDecode( p_vpar, p_vpar->picture.i_coding_type, i_structure );
-        P_picture->i_aspect_ratio = p_vpar->sequence.i_aspect_ratio;
         P_picture->i_matrix_coefficients = p_vpar->sequence.i_matrix_coefficients;
-        p_vpar->picture.i_field_width = ( p_vpar->sequence.i_width
-                    << ( 1 - p_vpar->picture.b_frame_structure ) );
-
-/* FIXME ! remove asap ?? */
-//memset( P_picture->p_data, 0, (p_vpar->sequence.i_mb_size*384));
 
         /* Update the reference pointers. */
         ReferenceUpdate( p_vpar, p_vpar->picture.i_coding_type, P_picture );
@@ -769,8 +836,15 @@ static void PictureHeader( vpar_thread_t * p_vpar )
         (i_structure != p_vpar->picture.i_current_structure);
     p_vpar->picture.b_current_field =
         (i_structure == BOTTOM_FIELD );
-
-    if( !p_vpar->p_config->p_stream_ctrl->b_grayscale )
+    p_vpar->picture.i_lum_stride = p_vpar->picture.p_picture->Y_PITCH
+        << ( 1 - p_vpar->picture.b_frame_structure );
+    p_vpar->picture.i_chrom_stride = p_vpar->picture.p_picture->U_PITCH
+        << ( 1 - p_vpar->picture.b_frame_structure );
+    /* We suppose the pitch is the same for U and V planes. */
+    p_vpar->picture.i_field_width = p_vpar->sequence.i_width
+        << ( 1 - p_vpar->picture.b_frame_structure );
+
+    if( !p_vpar->p_fifo->p_stream_ctrl->b_grayscale )
     {
         switch( p_vpar->sequence.i_chroma_format )
         {
@@ -859,7 +933,7 @@ static void PictureHeader( vpar_thread_t * p_vpar )
     }
 
     if( p_vpar->sequence.p_forward != NULL &&
-        p_vpar->sequence.p_forward->p_data == NULL )
+        p_vpar->sequence.p_forward->i_planes == 0 )
     {
         /* This can only happen with the fake picture created for section
          * 7.6.3.5. Clean up our mess. */
@@ -1014,17 +1088,6 @@ static void QuantMatrixExtension( vpar_thread_t * p_vpar )
         LoadMatrix( p_vpar, &p_vpar->sequence.chroma_nonintra_quant );
     }
     else
-    {
-        /* Link the chrominance intra matrix to the luminance one. */
-        LinkMatrix( &p_vpar->sequence.chroma_intra_quant,
-                    p_vpar->sequence.intra_quant.pi_matrix );
-    }
-    if( GetBits( &p_vpar->bit_stream, 1 ) )
-    {
-        /* Load non_intra_quantiser_matrix for chrominance. */
-        LoadMatrix( p_vpar, &p_vpar->sequence.chroma_nonintra_quant );
-    }
-    else
     {
         /* Link the chrominance nonintra matrix to the luminance one. */
         LinkMatrix( &p_vpar->sequence.chroma_nonintra_quant,