* 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"
/*
* 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 );
/*****************************************************************************
* 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 )
{
* 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 )
{
/*****************************************************************************
* 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;
/* 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;
}
/*****************************************************************************
* 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 )
{
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.
*/
*****************************************************************************/
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;
};
#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 ) ];
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) ?
/* 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 );
}
/*****************************************************************************
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 )
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
{
* 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;
}
}
{
/* 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 );
(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 )
{
}
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. */
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,