]> git.sesse.net Git - vlc/blobdiff - plugins/mpeg_vdec/vpar_headers.c
* ALL: changed __inline__ with inline (autoconf does the job for us anyway,
[vlc] / plugins / mpeg_vdec / vpar_headers.c
index f694f6763ae13847a522fe7505df15b2b52687c7..9516fdb41e77fb383111266e70c9e28d1ea8d5a8 100644 (file)
@@ -2,7 +2,7 @@
  * vpar_headers.c : headers parsing
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: vpar_headers.c,v 1.4 2001/12/10 04:53:11 sam Exp $
+ * $Id: vpar_headers.c,v 1.20 2002/05/18 17:47:47 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 "common.h"
-#include "intf_msg.h"
-#include "threads.h"
-#include "mtime.h"
+#include <videolan/vlc.h>
 
 #include "video.h"
 #include "video_output.h"
 #include "video_parser.h"
 #include "video_decoder.h"
 
-#include "modules_export.h"
-
 /*
  * 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 );
@@ -124,9 +117,9 @@ 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 )
     {
@@ -157,9 +150,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 )
     {
@@ -178,8 +170,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;
 
@@ -205,7 +197,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 )
     {
@@ -217,6 +209,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.
  */
@@ -243,36 +257,35 @@ 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++;
+    case SEQUENCE_HEADER_CODE:
+        p_vpar->c_sequences++;
+        SequenceHeader( p_vpar );
+        return 0;
+        break;
 
-            SequenceHeader( p_vpar );
-            return 0;
-            break;
+    case GROUP_START_CODE:
+        GroupHeader( p_vpar );
+        return 0;
+        break;
 
-        case GROUP_START_CODE:
-            GroupHeader( p_vpar );
-            return 0;
-            break;
+    case PICTURE_START_CODE:
+        PictureHeader( p_vpar );
+        return 0;
+        break;
 
-        case PICTURE_START_CODE:
-            PictureHeader( p_vpar );
-            return 0;
-            break;
+    case SEQUENCE_END_CODE:
+        intf_WarnMsg(3, "vpar warning: sequence end code received");
 
-        case SEQUENCE_END_CODE:
-            intf_DbgMsg("vpar debug: sequence end code received");
-            return 1;
-            break;
+        ReferenceUpdate( p_vpar, I_CODING_TYPE, NULL );
 
-        default:
-            break;
-        }
+        return 1;
+        break;
+
+    default:
+        break;
     }
 
     return 0;
@@ -303,14 +316,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 ) ];
 
@@ -381,12 +394,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_config->p_demux_data
+         && ( *(int*)(p_vpar->p_config->p_demux_data) & 0x7 ) )
+    {
+        i_aspect = *(int*)(p_vpar->p_config->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) ?
@@ -433,35 +498,58 @@ static void SequenceHeader( vpar_thread_t * p_vpar )
     /* Spawn a video output if there is none */
     vlc_mutex_lock( &p_vout_bank->lock );
     
+    if( p_vout_bank->i_count != 0 )
+    {
+        /* Take the first video output FIXME: take the best one */
+        p_vpar->p_vout = p_vout_bank->pp_vout[ 0 ];
+
+        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 )
+        {
+            p_vout_bank->pp_vout[ 0 ] = NULL;
+            p_vout_bank->i_count--;
+            vlc_mutex_unlock( &p_vout_bank->lock );
+            vout_DestroyThread( p_vpar->p_vout, NULL );
+            vlc_mutex_lock( &p_vout_bank->lock );
+
+            /* XXX: race condition here if p_vout_bank->i_count was updated */
+            if( p_vout_bank->i_count )
+            {
+                vlc_mutex_unlock( &p_vout_bank->lock );
+                intf_ErrMsg( "vpar error: can't open vout, aborting" );
+                p_vpar->p_fifo->b_error = 1;
+                return;
+            }
+        }
+    }
+
     if( p_vout_bank->i_count == 0 )
     {
         intf_WarnMsg( 1, "vpar: no vout present, spawning one" );
 
-        p_vpar->p_vout =
-            vout_CreateThread( NULL, p_vpar->sequence.i_width,
-                                     p_vpar->sequence.i_height,
-                                     99 + p_vpar->sequence.i_chroma_format,
-                                     p_vpar->sequence.i_aspect_ratio );
+        vlc_mutex_unlock( &p_vout_bank->lock );
+
+        p_vpar->p_vout = vout_CreateThread(
+                           NULL, 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 );
-
             p_vpar->p_fifo->b_error = 1;
-            /* XXX ! XXX ! XXX ! what to do here ? */
             return;
         }
         
+        vlc_mutex_lock( &p_vout_bank->lock );
+
         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 );
 }
@@ -484,6 +572,10 @@ static void PictureHeader( vpar_thread_t * p_vpar )
     int                 i_structure, i_previous_coding_type;
     boolean_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 )
     {
@@ -738,26 +830,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,
-                                        p_vpar->sequence.i_width,
-                                        p_vpar->sequence.i_height,
-                         /* XXX */ 99 + p_vpar->sequence.i_chroma_format,
-                                        p_vpar->sequence.i_aspect_ratio ) )
-             == 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: vout_CreatePicture failed, 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 ) );
 
         /* Update the reference pointers. */
         ReferenceUpdate( p_vpar, p_vpar->picture.i_coding_type, P_picture );
@@ -770,6 +857,13 @@ 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 );
+    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_config->p_stream_ctrl->b_grayscale )
     {
@@ -1015,17 +1109,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,