From e229f2696fca538ab58a308f18c1a9cd297c95ca Mon Sep 17 00:00:00 2001 From: Christophe Massiot Date: Tue, 28 Dec 1999 23:35:32 +0000 Subject: [PATCH] Suite du video_parser et du video_decoder. --- include/video_decoder.h.new | 63 +++ include/video_fifo.h | 20 +- include/video_parser.h | 112 ++---- include/vpar_blocks.h | 99 ++++- include/vpar_headers.h | 141 +++++++ src/video_decoder/vdec_idct.c | 65 +++ src/video_decoder/vdec_motion.c | 99 ++--- src/video_decoder/video_decoder.c | 163 ++++---- src/video_parser/video_fifo.c | 167 ++++---- src/video_parser/video_parser.c | 26 +- src/video_parser/vpar_blocks.c | 417 ++++++++++++++++++++ src/video_parser/vpar_headers.c | 630 +++++++++++++++++++----------- src/video_parser/vpar_motion.c | 54 +++ 13 files changed, 1507 insertions(+), 549 deletions(-) create mode 100644 include/video_decoder.h.new create mode 100644 include/vpar_headers.h create mode 100644 src/video_decoder/vdec_idct.c create mode 100644 src/video_parser/vpar_blocks.c create mode 100644 src/video_parser/vpar_motion.c diff --git a/include/video_decoder.h.new b/include/video_decoder.h.new new file mode 100644 index 0000000000..5dbf77e15a --- /dev/null +++ b/include/video_decoder.h.new @@ -0,0 +1,63 @@ +/***************************************************************************** + * video_decoder.h : video decoder thread + * (c)1999 VideoLAN + ***************************************************************************** + ***************************************************************************** + * Requires: + * "config.h" + * "common.h" + * "mtime.h" + * "vlc_thread.h" + * "input.h" + * "video.h" + * "video_output.h" + * "decoder_fifo.h" + *****************************************************************************/ + +/***************************************************************************** + * vdec_thread_t: video decoder thread descriptor + ***************************************************************************** + * ?? + *****************************************************************************/ +typedef struct vdec_thread_s +{ + /* Thread properties and locks */ + boolean_t b_die; /* `die' flag */ + boolean_t b_run; /* `run' flag */ + boolean_t b_error; /* `error' flag */ + boolean_t b_active; /* `active' flag */ + vlc_thread_t thread_id; /* id for thread functions */ + + /* Thread configuration */ + /* ?? */ + /*??*/ +// int *pi_status; + + + /* Input properties */ + video_parser_t * p_vpar; /* video_parser thread */ + +#ifdef STATS + /* Statistics */ + count_t c_loops; /* number of loops */ + count_t c_idle_loops; /* number of idle loops */ + count_t c_decoded_pictures; /* number of pictures decoded */ + count_t c_decoded_i_pictures; /* number of I pictures decoded */ + count_t c_decoded_p_pictures; /* number of P pictures decoded */ + count_t c_decoded_b_pictures; /* number of B pictures decoded */ +#endif +} vdec_thread_t; + +/***************************************************************************** + * Prototypes + *****************************************************************************/ + +/* Thread management functions */ +vdec_thread_t * vdec_CreateThread ( vpar_thread_t *p_vpar /*, int *pi_status */ ); +void vdec_DestroyThread ( vdec_thread_t *p_vdec /*, int *pi_status */ ); + +/* Time management functions */ +/* ?? */ + +/* Dynamic thread settings */ +/* ?? */ diff --git a/include/video_fifo.h b/include/video_fifo.h index f115ddd80d..4c1ad5e3a4 100644 --- a/include/video_fifo.h +++ b/include/video_fifo.h @@ -29,7 +29,7 @@ /***************************************************************************** * video_fifo_t ***************************************************************************** - * This rotative FIFO contains undecoded pictures that are to be decoded + * This rotative FIFO contains undecoded macroblocks that are to be decoded *****************************************************************************/ typedef struct video_fifo_s { @@ -37,7 +37,7 @@ typedef struct video_fifo_s vlc_cond_t wait; /* fifo data conditional variable */ /* buffer is an array of undec_picture_t pointers */ - undec_picture_t * buffer[VFIFO_SIZE + 1]; + macroblock_t * buffer[VFIFO_SIZE + 1]; int i_start; int i_end; @@ -48,22 +48,22 @@ typedef struct video_fifo_s * video_buffer_t ***************************************************************************** * This structure enables the parser to maintain a list of free - * undec_picture_t structures + * macroblock_t structures *****************************************************************************/ typedef struct video_buffer_s { vlc_mutex_t lock; /* buffer data lock */ - undec_picture_t p_undec_p[VFIFO_SIZE + 1]; - undec_picture_t * pp_undec_free[VFIFO_SIZE+1]; /* this is a LIFO */ + macroblock_t p_macroblocks[VFIFO_SIZE + 1]; + macroblock_t * pp_mb_free[VFIFO_SIZE+1]; /* this is a LIFO */ int i_index; } video_buffer_t; /***************************************************************************** * Prototypes *****************************************************************************/ -undec_picture_t * vpar_GetPicture( video_fifo_t * p_fifo ); -undec_picture_t * vpar_NewPicture( video_fifo_t * p_fifo ); -void vpar_DecodePicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p ); -void vpar_ReleasePicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p ); -void vpar_DestroyPicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p ); +macroblock_t * vpar_GetMacroblock( video_fifo_t * p_fifo ); +macroblock_t * vpar_NewMacroblock( video_fifo_t * p_fifo ); +void vpar_DecodeMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb ); +void vpar_ReleaseMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb ); +void vpar_DestroyMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb ); diff --git a/include/video_parser.h b/include/video_parser.h index 825c3c1a4c..86b35f2797 100644 --- a/include/video_parser.h +++ b/include/video_parser.h @@ -1,8 +1,8 @@ -/******************************************************************************* +/***************************************************************************** * video_parser.h : video parser thread * (c)1999 VideoLAN - ******************************************************************************* - ******************************************************************************* + ***************************************************************************** + ***************************************************************************** * Requires: * "config.h" * "common.h" @@ -13,44 +13,22 @@ * "video_output.h" * "decoder_fifo.h" * "video_fifo.h" - *******************************************************************************/ + * "vpar_headers.h" + *****************************************************************************/ -/******************************************************************************* - * sequence_t : sequence descriptor - ******************************************************************************* - * ?? - *******************************************************************************/ -typedef struct sequence_s -{ - u16 i_height, i_width; - u16 i_mb_height, i_mb_width; - unsigned int i_aspect_ratio; - double d_frame_rate; - unsigned int i_chroma_format; - boolean_t b_mpeg2; - boolean_t b_progressive; - - /* Parser context */ - picture_t * p_forward, p_backward; - pel_lookup_table_t * p_frame_lum_lookup, p_field_lum_lookup; - pel_lookup_table_t * p_frame_chroma_lookup, p_field_chroma_lookup; - quant_matrix_t intra_quant, nonintra_quant; - quant_matrix_t chroma_intra_quant, chroma_nonintra_quant; -} sequence_t; - -/******************************************************************************* +/***************************************************************************** * vpar_thread_t: video parser thread descriptor - ******************************************************************************* + ***************************************************************************** * ?? - *******************************************************************************/ + *****************************************************************************/ typedef struct vpar_thread_s { /* Thread properties and locks */ - boolean_t b_die; /* `die' flag */ - boolean_t b_run; /* `run' flag */ - boolean_t b_error; /* `error' flag */ - boolean_t b_active; /* `active' flag */ - vlc_thread_t thread_id; /* id for thread functions */ + boolean_t b_die; /* `die' flag */ + boolean_t b_run; /* `run' flag */ + boolean_t b_error; /* `error' flag */ + boolean_t b_active; /* `active' flag */ + vlc_thread_t thread_id; /* id for thread functions */ /* Thread configuration */ /* ?? */ @@ -59,67 +37,45 @@ typedef struct vpar_thread_s /* Input properties */ - decoder_fifo_t fifo; /* PES input fifo */ + decoder_fifo_t fifo; /* PES input fifo */ /* The bit stream structure handles the PES stream at the bit level */ bit_stream_t bit_stream; /* Output properties */ - vout_thread_t * p_vout; /* video output thread */ - int i_stream; /* video stream id */ + vout_thread_t * p_vout; /* video output thread */ + int i_stream; /* video stream id */ /* Decoder properties */ - struct vdec_thread_s * p_vdec[MAX_VDEC]; + struct vdec_thread_s * p_vdec[NB_VDEC]; video_fifo_t vfifo; video_buffer_t vbuffer; /* Parser properties */ - sequence_t sequence; + sequence_t sequence; + picture_parsing_t picture; + slice_parsing_t slice; + macroblock_parsing_t mb; #ifdef STATS /* Statistics */ - count_t c_loops; /* number of loops */ - count_t c_idle_loops; /* number of idle loops */ - count_t c_sequences; /* number of sequences */ - count_t c_pictures; /* number of pictures read */ - count_t c_i_pictures; /* number of I pictures read */ - count_t c_p_pictures; /* number of P pictures read */ - count_t c_b_pictures; /* number of B pictures read */ - count_t c_decoded_pictures; /* number of pictures decoded */ - count_t c_decoded_i_pictures; /* number of I pictures decoded */ - count_t c_decoded_p_pictures; /* number of P pictures decoded */ - count_t c_decoded_b_pictures; /* number of B pictures decoded */ + count_t c_loops; /* number of loops */ + count_t c_idle_loops; /* number of idle loops */ + count_t c_sequences; /* number of sequences */ + count_t c_pictures; /* number of pictures read */ + count_t c_i_pictures; /* number of I pictures read */ + count_t c_p_pictures; /* number of P pictures read */ + count_t c_b_pictures; /* number of B pictures read */ + count_t c_decoded_pictures; /* number of pictures decoded */ + count_t c_decoded_i_pictures; /* number of I pictures decoded */ + count_t c_decoded_p_pictures; /* number of P pictures decoded */ + count_t c_decoded_b_pictures; /* number of B pictures decoded */ #endif } vpar_thread_t; -/******************************************************************************* - * Standard start codes - *******************************************************************************/ -#define PICTURE_START_CODE 0x100 -#define SLICE_START_CODE_MIN 0x101 -#define SLICE_START_CODE_MAX 0x1AF -#define USER_DATA_START_CODE 0x1B2 -#define SEQUENCE_HEADER_CODE 0x1B3 -#define SEQUENCE_ERROR_CODE 0x1B4 -#define EXTENSION_START_CODE 0x1B5 -#define SEQUENCE_END_CODE 0x1B7 -#define GROUP_START_CODE 0x1B8 - -/* extension start code IDs */ - -#define SEQUENCE_EXTENSION_ID 1 -#define SEQUENCE_DISPLAY_EXTENSION_ID 2 -#define QUANT_MATRIX_EXTENSION_ID 3 -#define COPYRIGHT_EXTENSION_ID 4 -#define SEQUENCE_SCALABLE_EXTENSION_ID 5 -#define PICTURE_DISPLAY_EXTENSION_ID 7 -#define PICTURE_CODING_EXTENSION_ID 8 -#define PICTURE_SPATIAL_SCALABLE_EXTENSION_ID 9 -#define PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID 10 - -/******************************************************************************* +/***************************************************************************** * Prototypes - *******************************************************************************/ + *****************************************************************************/ /* Thread management functions */ vpar_thread_t * vpar_CreateThread ( /* video_cfg_t *p_cfg, */ input_thread_t *p_input /*, diff --git a/include/vpar_blocks.h b/include/vpar_blocks.h index da15c9e9b4..dcbc0fc61d 100644 --- a/include/vpar_blocks.h +++ b/include/vpar_blocks.h @@ -16,16 +16,97 @@ *****************************************************************************/ /***************************************************************************** - * quant_matrix_t : Quantization Matrix + * macroblock_t : information on a macroblock + *****************************************************************************/ +typedef struct macroblock_s +{ + picture_t * p_picture; + int i_mb_x, i_mb_y; + int i_structure; + int i_l_x, i_l_y; /* position of macroblock (lum) */ + int i_c_x, i_c_y; /* position of macroblock (chroma) */ + int i_structure; + int i_chroma_nb_blocks; /* nb of bks for a chr comp */ + + /* IDCT information */ + elem_t ppi_blocks[12][64]; /* blocks */ + f_idct_t pf_idct[12]; /* sparse IDCT or not ? */ + int pi_sparse_pos[12]; + + /* Motion compensation information */ + f_motion_t pf_motion; /* function to use for motion comp */ + f_chroma_motion_t pf_chroma_motion; + picture_t * p_backw_top, p_backw_bot; + picture_t * p_forw_top, p_forw_bot; + int i_field_select_backw_top, i_field_select_backw_bot; + int i_field_select_forw_top, i_field_select_forw_bot; + int pi_motion_vectors_backw_top[2]; + int pi_motion_vectors_backw_bot[2]; + int pi_motion_vectors_forw_top[2]; + int pi_motion_vectors_forw_bot[2]; + + /* AddBlock information */ + f_addb_t pf_addb[12]; + data_t * p_data[12]; /* positions of blocks in picture */ + int i_lum_incr, i_chroma_incr; +} macroblock_t; + +/***************************************************************************** + * macroblock_parsing_t : parser context descriptor #3 + *****************************************************************************/ +typedef struct +{ + int i_mb_type, i_motion_type, i_mv_count, i_mv_format; + int i_coded_block_pattern; + boolean_t b_dct_type; +} macroblock_parsing_t; + +/***************************************************************************** + * LoadQuantizerScale ***************************************************************************** - * ?? + * Quantizer scale factor (ISO/IEC 13818-2 7.4.2.2) *****************************************************************************/ -typedef struct quant_matrix_s +static __inline__ void LoadQuantizerScale( vpar_thread_t * p_vpar ) { - int pi_matrix[64]; - boolean_t b_allocated; - /* Has the matrix been allocated by vpar_headers ? */ -} quant_matrix_t; + /* Quantization coefficient table */ + static unsigned char ppi_quantizer_scale[3][32] = + { + /* MPEG-2 */ + { + /* q_scale_type */ + /* linear */ + 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30, + 32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62 + }, + { + /* non-linear */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 10,12,14,16,18,20, 22, + 24,28,32,36,40,44,48,52,56,64,72,80,88,96,104,112 + }, + /* MPEG-1 */ + { + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, + 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 + } + }; + + p_vpar->slice.i_quantizer_scale = ppi_quantizer_scale + [(!p_vpar->sequence.b_mpeg2 << 1) | p_vpar->picture.b_q_scale_type] + [GetBits( &p_vpar->bit_stream, 5 )]; +} + +/***************************************************************************** + * Standard codes + *****************************************************************************/ +/* Macroblock types */ +#define MB_INTRA 1 +#define MB_PATTERN 2 +#define MB_MOTION_BACKWARD 4 +#define MB_MOTION_FORWARD 8 +#define MB_QUANT 16 -extern int * pi_default_intra_quant; -extern int * pi_default_nonintra_quant; +/* Motion types */ +#define MOTION_FIELD 1 +#define MOTION_FRAME 2 +#define MOTION_16X8 2 +#define MOTION_DMV 3 diff --git a/include/vpar_headers.h b/include/vpar_headers.h new file mode 100644 index 0000000000..cb992bf478 --- /dev/null +++ b/include/vpar_headers.h @@ -0,0 +1,141 @@ +/***************************************************************************** + * vpar_headers.h : video parser : headers parsing + * (c)1999 VideoLAN + ***************************************************************************** + ***************************************************************************** + * Requires: + * "config.h" + * "common.h" + * "mtime.h" + * "vlc_thread.h" + * "input.h" + * "video.h" + * "video_output.h" + * "decoder_fifo.h" + * "video_fifo.h" + *****************************************************************************/ + +/***************************************************************************** + * Function pointers + *****************************************************************************/ +typedef (void *) f_slice_header_t( vpar_thread_t*, int*, int, elem_t*, u32); + +/***************************************************************************** + * quant_matrix_t : Quantization Matrix + *****************************************************************************/ +typedef struct quant_matrix_s +{ + int pi_matrix[64]; + boolean_t b_allocated; + /* Has the matrix been allocated by vpar_headers ? */ +} quant_matrix_t; + +extern int * pi_default_intra_quant; +extern int * pi_default_nonintra_quant; + +/***************************************************************************** + * sequence_t : sequence descriptor + *****************************************************************************/ +typedef struct sequence_s +{ + u32 i_height, i_width, i_chroma_width, i_size; + u32 i_mb_height, i_mb_width, i_mb_size; + unsigned int i_aspect_ratio; + double d_frame_rate; + unsigned int i_chroma_format; + int i_chroma_nb_blocks; + boolean_t b_mpeg2; + boolean_t b_progressive; + unsigned int i_scalable_mode; + f_slice_header_t pf_slice_header; + quant_matrix_t intra_quant, nonintra_quant; + quant_matrix_t chroma_intra_quant, chroma_nonintra_quant; + (void *) pf_decode_mv( vpar_thread_t *, int ); + (void *) pf_decode_pattern( vpar_thread_t * ); + + /* Parser context */ + picture_t * p_forward, p_backward; +} sequence_t; + +/***************************************************************************** + * picture_parsing_t : parser context descriptor + *****************************************************************************/ +typedef struct picture_parsing_s +{ + boolean_t b_full_pel_forward_vector, b_full_pel_backward_vector; + int i_forward_f_code, i_backward_f_code; + + int ppi_f_code[2][2]; + int i_intra_dc_precision; + boolean_t b_frame_pred_frame_dct, b_q_scale_type; + boolean_t b_alternate_scan, b_progressive_frame; + boolean_t b_top_field_first, b_concealment_mv; + + int i_lum_incr, i_chroma_incr; + + /* Used for second field management */ + int i_current_structure; + + picture_t * p_picture; + macroblock_t * pp_mb[MAX_MB]; + + /* Relative to the current field */ + int i_coding_type, i_structure; + boolean_t b_frame_structure; + (int *) pf_macroblock_type( vpar_thread_t * ); + + boolean_t b_error; +} picture_parsing_t; + +/***************************************************************************** + * slice_parsing_t : parser context descriptor #2 + *****************************************************************************/ +typedef struct slice_parsing_s +{ + unsigned char i_quantizer_scale; + int pi_dc_dct_pred[3]; /* ISO/IEC 13818-2 7.2.1 */ + int pppi_pmv[2][2][2]; /* Motion vect predictors, 7.6.3 */ +} slice_parsing_t; + +/***************************************************************************** + * Standard codes + *****************************************************************************/ +#define PICTURE_START_CODE 0x100 +#define SLICE_START_CODE_MIN 0x101 +#define SLICE_START_CODE_MAX 0x1AF +#define USER_DATA_START_CODE 0x1B2 +#define SEQUENCE_HEADER_CODE 0x1B3 +#define SEQUENCE_ERROR_CODE 0x1B4 +#define EXTENSION_START_CODE 0x1B5 +#define SEQUENCE_END_CODE 0x1B7 +#define GROUP_START_CODE 0x1B8 + +/* extension start code IDs */ +#define SEQUENCE_EXTENSION_ID 1 +#define SEQUENCE_DISPLAY_EXTENSION_ID 2 +#define QUANT_MATRIX_EXTENSION_ID 3 +#define COPYRIGHT_EXTENSION_ID 4 +#define SEQUENCE_SCALABLE_EXTENSION_ID 5 +#define PICTURE_DISPLAY_EXTENSION_ID 7 +#define PICTURE_CODING_EXTENSION_ID 8 +#define PICTURE_SPATIAL_SCALABLE_EXTENSION_ID 9 +#define PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID 10 + +/* scalable modes */ +#define SC_NONE 0 +#define SC_DP 1 +#define SC_SPAT 2 +#define SC_SNR 3 +#define SC_TEMP 4 + +/* Pictures types */ +#define I_CODING_TYPE 1 +#define P_CODING_TYPE 2 +#define B_CODING_TYPE 3 +#define D_CODING_TYPE 4 /* MPEG-1 ONLY */ +/* other values are reserved */ + +/* Structures */ +#define TOP_FIELD 1 +#define BOTTOM_FIELD 2 +#define FRAME_STRUCTURE 3 diff --git a/src/video_decoder/vdec_idct.c b/src/video_decoder/vdec_idct.c new file mode 100644 index 0000000000..7128eb6c1f --- /dev/null +++ b/src/video_decoder/vdec_idct.c @@ -0,0 +1,65 @@ +/***************************************************************************** + * vdec_idct.c : IDCT functions + * (c)1999 VideoLAN + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "common.h" +#include "mtime.h" +#include "vlc_thread.h" + +#include "intf_msg.h" +#include "debug.h" /* ?? temporaire, requis par netlist.h */ + +#include "input.h" +#include "input_netlist.h" +#include "decoder_fifo.h" +#include "video.h" +#include "video_output.h" +#include "video_parser.h" + +#include "undec_picture.h" +#include "video_fifo.h" +#include "video_decoder.h" + +/* + * Local prototypes + */ + +/* Our current implementation is a fast DCT, we might move to a fast DFT or + * an MMX DCT in the future. */ + +/***************************************************************************** + * vdec_DummyIDCT : dummy function that does nothing + *****************************************************************************/ +void vdec_DummyIDCT( elem_t * p_block, int i_idontcare ) +{ +} + +/***************************************************************************** + * vdec_SparseIDCT : IDCT function for sparse matrices + *****************************************************************************/ +void vdec_SparseIDCT( elem_t * p_block, int i_sparse_pos ) +{ + /* Copy from mpeg_play */ +} + +/***************************************************************************** + * vdec_IDCT : IDCT function for normal matrices + *****************************************************************************/ +void vdec_IDCT( elem_t * p_block, int i_idontcare ) +{ + +} diff --git a/src/video_decoder/vdec_motion.c b/src/video_decoder/vdec_motion.c index 310d41b6d6..87f7dad82e 100644 --- a/src/video_decoder/vdec_motion.c +++ b/src/video_decoder/vdec_motion.c @@ -3,8 +3,6 @@ * (c)1999 VideoLAN *****************************************************************************/ -/* ?? passer en terminate/destroy avec les signaux supplémentaires */ - /***************************************************************************** * Preamble *****************************************************************************/ @@ -40,52 +38,46 @@ * Local prototypes */ +typedef (void *) f_motion_c_t( coeff_t *, pel_lookup_table_t *, + int, coeff_t *, int, int, + int, int, int, int, int ); + /***************************************************************************** - * vdec_MotionCompensation : motion compensation + * vdec_DummyRecon : motion compensation for an intra macroblock *****************************************************************************/ -void vdec_MotionFrame( vdec_thread_t * p_vdec, - undec_picture_t * p_undec_p, int i_mb, - f_motion_mb_t pf_mb_motion ) +void vdec_DummyRecon( macroblock_t * p_mb ) { - static int p_chroma_nb_blocks[4] = {1, 2, 4}; - static int p_chroma_nb_elems[4] = {0, 64, 128, 256}; +} - int i_mb_x, i_mb_y; /* Position of our macroblock in the final picture */ - elem_t * p_y, p_u, p_v; /* Pointers to our picture's data */ +/***************************************************************************** + * vdec_ForwardRecon : motion compensation for a forward predicted macroblock + *****************************************************************************/ +void vdec_ForwardRecon( macroblock_t * p_mb ) +{ + +} + +/***************************************************************************** + * vdec_BackwardRecon : motion compensation for a backward predicted macroblock + *****************************************************************************/ +void vdec_BackwardRecon( macroblock_t * p_mb ) +{ -#define P_mb_info p_undec_p->p_mb_info[i_mb] - - i_mb_x = (i_mb << 5) % p_undec_p->p_picture->i_width; - i_mb_y = (i_mb << 5) / p_undec_p->p_picture->i_width; - p_y = &p_undec_p->p_picture->p_y[256*i_mb]; - p_u = &p_undec_p->p_picture->p_u[p_chroma_nb_elems[p_undec_p->p_picture->i_chroma_type]*i_mb]; - p_v = &p_undec_p->p_picture->p_v[p_chroma_nb_elems[p_undec_p->p_picture->i_chroma_type]*i_mb]; - - if( (p_undec_p->i_coding_type == P_CODING_TYPE) || - (P_mb_info->i_mb_type & MB_MOTION_FORWARD) ) - { - if( (P_mb_info->i_motion_type == MOTION_FRAME) || - !(P_mb_info->i_mb_type & MB_INTRA) ) - { - MotionBlock( p_undec_p->p_forward->p_u, - p_undec_p->p_forward->p_lookup_lum, - p_undec_p->p_picture->i_width, - p_u, i_mb_x, i_mb_y, - p_undec_p->p_picture->i_width, - p_undec_p->ppp_motion_vectors[0][0][0], - p_undec_p->ppp_motion_vectors[0][0][1] ); - } - } } /***************************************************************************** - * MotionMacroblock : motion compensation for a macroblock + * vdec_BidirectionalRecon : motion compensation for a bidirectionally + * predicted macroblock *****************************************************************************/ -void vdec_MotionMacroblock420( coeff_t * p_src, pel_lookup_table_t * p_lookup, - int i_width_line, - coeff_t * p_dest, int i_dest_x, i_dest_y, - int i_stride_line, - i_mv1_x, i_mv1_y, i_mv2_x, i_mv2_y ) +void vdec_BidirectionalRecon( macroblock_t * p_mb ) +{ + +} + +/***************************************************************************** + * vdec_MotionMacroblock420 : motion compensation for a 4:2:0 macroblock + *****************************************************************************/ +void vdec_MotionMacroblock420( macroblock_t * p_mb ) { /* Luminance */ MotionBlock( p_undec_p->p_forward->p_u, p_undec_p->p_forward->p_lookup_lum, @@ -105,12 +97,9 @@ void __inline__ MotionBlock( coeff_t * p_src, pel_lookup_table_t * p_lookup, int i_stride_line, i_mv1_x, i_mv1_y, i_mv2_x, i_mv2_y ) { - static (void *) ComponentMode( coeff_t * p_src, - pel_lookup_table_t * p_lookup, - coeff_t * p_dest, int i_dest_x, i_dest_y, - int i_stride_line, i_mv_x, i_mv_y )[4] - = { ComponentNN, ComponentNH, ComponentHN, - ComponentHH }; + static f_motion_c_t ComponentMode[4] + = { &ComponentNN, &ComponentNH, &ComponentHN, + &ComponentHH }; int i_mode; @@ -118,7 +107,8 @@ void __inline__ MotionBlock( coeff_t * p_src, pel_lookup_table_t * p_lookup, ComponentMode[i_mode]( p_src, p_lookup, i_width_line, p_dest, i_dest_x, i_dest_y, - i_stride_line, i_mv_x >> 1, i_mv_y >> 1 ); + i_stride_line, i_mv1_x >> 1, i_mv1_y >> 1, + i_mv2_x >> 1, i_mv2_y >> 1 ); } /***************************************************************************** @@ -132,9 +122,22 @@ void ComponentNN( coeff_t * p_src, pel_lookup_table_t * p_lookup, int i_vpos; register int i_hpos, i_src_loc; - i_src_loc = (i_dest_y + i_mv_y)*i_width_line + i_dest_x + i_mv_x; + i_src_loc = (i_dest_y + i_mv1_y)*i_width_line + i_dest_x + i_mv1_x; - for( i_vpos = 0; i_vpos < 8; i_vpos++ ) + for( i_vpos = 0; i_vpos < 4; i_vpos++ ) + { + for( i_hpos = 0; i_hpos < 8; i_hpos++ ) + { + p_dest[i_hpos] += p_src[p_lookup->pi_pel[i_src_loc + i_hpos]]; + } + + p_dest += 8; + i_src_loc += i_stride_line; + } + + i_src_loc = (i_dest_y + i_mv2_y)*i_width_line + i_dest_x + i_mv2_x; + + for( i_vpos = 4; i_vpos < 8; i_vpos++ ) { for( i_hpos = 0; i_hpos < 8; i_hpos++ ) { diff --git a/src/video_decoder/video_decoder.c b/src/video_decoder/video_decoder.c index 00df1e880a..ff0328e0ad 100644 --- a/src/video_decoder/video_decoder.c +++ b/src/video_decoder/video_decoder.c @@ -43,8 +43,8 @@ static int InitThread ( vdec_thread_t *p_vdec ); static void RunThread ( vdec_thread_t *p_vdec ); static void ErrorThread ( vdec_thread_t *p_vdec ); static void EndThread ( vdec_thread_t *p_vdec ); -static void DecodePicture ( vdec_thread_t *p_vdec, - undec_picture_t * p_undec_p ); +static void DecodeMacroblock ( vdec_thread_t *p_vdec, + macroblock_t * p_mb ); /******************************************************************************* * vdec_CreateThread: create a video decoder thread @@ -165,11 +165,11 @@ static void RunThread( vdec_thread_t *p_vdec ) */ while( (!p_vdec->b_die) && (!p_vdec->b_error) ) { - undec_picture_t * p_undec_p; + macroblock_t * p_mb; - if( (p_undec_p = GetPicture( p_vdec->p_vpar->p_fifo )) != NULL ) + if( (p_mb = GetMacroblock( &p_vdec->p_vpar.vfifo )) != NULL ) { - DecodePicture( p_vdec, p_undec_p ); + DecodeMacroblock( p_vdec, p_mb ); } } @@ -220,92 +220,101 @@ static void EndThread( vdec_thread_t *p_vdec ) } /******************************************************************************* - * DecodePicture : decode a picture + * DecodeMacroblock : decode a macroblock of a picture *******************************************************************************/ -static void DecodePicture( vdec_thread_t *p_vdec, undec_picture_t * p_undec_p ) +static void DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb ) { - static int pi_chroma_nb_blocks[4] = {0, 1, 2, 4}; - static int pi_chroma_nb_coeffs[4] = {0, 64, 128, 256}; - static f_motion_mb_t ppf_chroma_motion[4] = { NULL, - &vdec_MotionMacroBlock420, - &vdec_MotionMacroBlock422, - &vdec_MotionMacroBlock444 }; - static f_motion_t pppf_motion_forward[4][2] = { - {NULL, NULL} /* I picture */ - {&vdec_MotionForward, &vdec_MotionForward} /* P */ - {NULL, &vdec_MotionForward} /* B */ - {NULL, NULL} /* D */ }; - static f_motion_t pppf_motion_backward[4][2] = { - {NULL, NULL} /* I picture */ - {NULL, NULL} /* P */ - {NULL, &vdec_MotionBackward} /* B */ - {NULL, NULL} /* D */ }; - static f_motion_t ppf_motion[4] = { NULL, - &vdec_MotionTopFirst, - &vdec_MotionBottomFirst, - &vdec_MotionFrame }; - - int i_mb, i_b, i_totb; - coeff_t * p_y, p_u, p_v; - f_motion_mb_t pf_chroma_motion; - f_motion_t pf_motion_forward, pf_motion_backward; - int i_chroma_nb_blocks, i_chroma_nb_coeffs; - - p_y = (coeff_t *)p_undec_p->p_picture->p_y; - p_u = (coeff_t *)p_undec_p->p_picture->p_u; - p_v = (coeff_t *)p_undec_p->p_picture->p_v; - -#define I_chroma_format p_undec_p->p_picture->i_chroma_format - pf_chroma_motion = ppf_chroma_motion[I_chroma_format]; - pf_motion_forward - pf_motion = ppf_motion[p_undec_p->i_structure]; + int i_b; - i_chroma_nb_blocks = pi_chroma_nb_blocks[I_chroma_format]; - i_chroma_nb_coeffs = pi_chroma_nb_coeffs[I_chroma_format]; -#undef I_chroma_format + /* + * Motion Compensation (ISO/IEC 13818-2 section 7.6) + */ + (*p_mb->pf_motion)( p_mb ); - for( i_mb = 0; i_mb < p_undec_p->i_mb_height*p_undec_p->i_mb_width; i_mb++ ) + /* luminance */ + for( i_b = 0; i_b < 4; i_b++ ) { -#define P_mb_info p_undec_p->p_mb_info[i_ref] - /* * Inverse DCT (ISO/IEC 13818-2 section Annex A) */ - - /* Luminance : always 4 blocks */ - for( i_b = 0; i_b < 4; i_b++ ) - { - (*P_mb_info.p_idct_function[i_b])( p_y + i_b*64 ); - } - i_totb = 4; - - /* Chrominance Cr */ - for( i_b = 0; i_b < i_chroma_nb_blocks; i_b++ ) - { - (*P_mb_info.p_idct_function[i_totb + i_b])( p_u + i_b*64 ); - } - i_totb += i_chroma_nb_blocks; - - /* Chrominance Cb */ - for( i_b = 0; i_b < i_chroma_nb_blocks; i_b++ ) - { - (*P_mb_info.p_idct_function[i_totb + i_b])( p_v + i_b*64 ); - } + (*p_mb->pf_idct[i_b])( p_mb, p_mb->ppi_blocks[i_b], p_mb->pi_sparse_pos[i_b] ); + + /* + * Adding prediction and coefficient data (ISO/IEC 13818-2 section 7.6.8) + */ + (*p_mb->pf_addb[i_b])( p_mb->ppi_blocks[i_b], + p_mb->p_data[i_b], p_mb->i_lum_incr ); + } + /* chrominance */ + for( i_b = 4; i_b < 4 + 2*p_mb->i_chroma_nb_blocks; i_b++ ) + { /* - * Motion Compensation (ISO/IEC 13818-2 section 7.6) + * Inverse DCT (ISO/IEC 13818-2 section Annex A) */ - (*pf_motion)( p_vdec, p_undec_p, i_mb, pf_chroma_motion ); + (*p_mb->pf_idct[i_b])( p_mb, p_mb->ppi_blocks[i_b], p_mb->pi_sparse_pos[i_b] ); - p_y += 256; - p_u += i_chroma_nb_coeffs; - p_v += i_chroma_nb_coeffs; -#undef P_mb_info + /* + * Adding prediction and coefficient data (ISO/IEC 13818-2 section 7.6.8) + */ + (*p_mb->pf_addb[i_b])( p_mb->ppi_blocks[i_b], + p_mb->p_data[i_b], p_mb->i_chroma_incr ); } /* - * Decoding is finished, mark the picture ready for displaying and free - * unneeded memory + * Decoding is finished, release the macroblock and free + * unneeded memory. */ - vpar_ReleasePicture( p_vdec->p_vpar->p_fifo, p_undec_p ); + vpar_ReleaseMacroblock( &p_vdec->p_vpar.vfifo, p_mb ); +} + +/******************************************************************************* + * vdec_AddBlock : add a block + *******************************************************************************/ +void vdec_AddBlock( elem_t * p_block, data_t * p_data, int i_incr ) +{ + int i_x, i_y; + + for( i_y = 0; i_y < 8; i_y++ ) + { + for( i_x = 0; i_x < 8; i_x++ ) + { + /* ??? Need clip to be MPEG-2 compliant */ + *p_data++ += *p_block++; + } + p_data += i_incr; + } +} + +/******************************************************************************* + * vdec_CopyBlock : copy a block + *******************************************************************************/ +void vdec_CopyBlock( elem_t * p_block, data_t * p_data, int i_incr ) +{ + int i_x, i_y; + + for( i_y = 0; i_y < 8; i_y++ ) + { +#ifndef VDEC_DFT + /* elem_t and data_t are the same */ + memcopy( p_data, p_block, 8*sizeof(data_t) ); + p_data += i_incr+8; + p_block += 8; +#else + for( i_x = 0; i_x < 8; i_x++ ) + { + /* ??? Need clip to be MPEG-2 compliant */ + /* ??? Why does the reference decoder add 128 ??? */ + *p_data++ = *p_block++; + } + p_data += i_incr; +#endif + } +} + +/******************************************************************************* + * vdec_DummyBlock : dummy function that does nothing + *******************************************************************************/ +void vdec_DummyBlock( elem_t * p_block, data_t * p_data, int i_incr ) +{ } diff --git a/src/video_parser/video_fifo.c b/src/video_parser/video_fifo.c index 8242894a84..0831aa4623 100644 --- a/src/video_parser/video_fifo.c +++ b/src/video_parser/video_fifo.c @@ -30,7 +30,7 @@ #include "video_output.h" #include "video_parser.h" -#include "undec_picture.h" +#include "macroblock.h" #include "video_fifo.h" #include "video_decoder.h" @@ -39,7 +39,7 @@ *****************************************************************************/ void vpar_InitFIFO( vpar_thread_t * p_vpar ) { - int i_dummy; + int i_dummy; /* Initialize mutex and cond */ vlc_mutex_init( p_vpar->vfifo.lock ); @@ -54,17 +54,16 @@ void vpar_InitFIFO( vpar_thread_t * p_vpar ) i_index = VFIFO_SIZE; /* all structures are available */ for( i_dummy = 0; i_dummy < VFIFO_SIZE + 1; i_dummy++ ) { - p_vpar->vfifo.pp_undec_free[i_dummy] = p_vpar->vfifo.p_undec_p + i; - p_vpar->vfifo.p_undec_p[i].p_mb_info = NULL; + p_vpar->vfifo.pp_mb_free[i_dummy] = p_vpar->vfifo.p_macroblocks + i; } } /***************************************************************************** - * vpar_GetPicture : return a picture to be decoded + * vpar_GetMacroblock : return a macroblock to be decoded *****************************************************************************/ -undec_picture_t * vpar_GetPicture( video_fifo_t * p_fifo ) +macroblock_t * vpar_GetMacroblock( video_fifo_t * p_fifo ) { - undec_picture_t * p_undec_p; + macroblock_t * p_mb; vlc_mutex_lock( &p_fifo->lock ); while( VIDEO_FIFO_ISEMPTY( *p_fifo ) ) @@ -77,20 +76,20 @@ undec_picture_t * vpar_GetPicture( video_fifo_t * p_fifo ) } } - p_undec_p = VIDEO_FIFO_START( *p_fifo ); + p_mb = VIDEO_FIFO_START( *p_fifo ); VIDEO_FIFO_INCSTART( *p_fifo ); vlc_mutex_unlock( &p_fifo->lock ); - return( p_undec_p ); + return( p_mb ); } /***************************************************************************** - * vpar_NewPicture : return a buffer for the parser + * vpar_NewMacroblock : return a buffer for the parser *****************************************************************************/ -undec_picture_t * vpar_NewPicture( video_fifo_t * p_fifo ) +macroblock_t * vpar_NewMacroblock( video_fifo_t * p_fifo ) { - undec_picture_t * p_undec_p; + macroblock_t * p_mb; #define P_buffer p_fifo->p_vpar.vbuffer vlc_mutex_lock( &P_buffer->lock ); @@ -100,128 +99,100 @@ undec_picture_t * vpar_NewPicture( video_fifo_t * p_fifo ) return NULL; } - p_undec_p = P_buffer->pp_undec_free[ P_buffer->i_index-- ]; + p_mb = P_buffer->pp_undec_free[ P_buffer->i_index-- ]; #undef P_buffer vlc_mutex_unlock( &P_buffer->lock ); - return( p_undec_p ); + return( p_mb ); } /***************************************************************************** - * vpar_DecodePicture : put a picture in the video fifo, if it is decodable + * vpar_DecodeMacroblock : put a macroblock in the video fifo *****************************************************************************/ -void vpar_DecodePicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p ) +void vpar_DecodeMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb ) { - boolean_t b_decodable; - - switch( p_undec_p ) - { - case B_CODING_TYPE: - b_decodable = ((p_undec_p->p_backward_p != NULL) && - (p_undec_p->p_forward_p != NULL)); - break; - case P_CODING_TYPE: - b_decodable = (p_undec_p->p_backward_p != NULL); - break; - case I_CODING_TYPE: - case D_CODING_TYPE: - b_decodable = TRUE; - break; - default: - /* That should not happen */ - } - - if( b_decodable ) - { - /* Place picture in the video FIFO */ - vlc_mutex_lock( &p_fifo->lock ); + /* Place picture in the video FIFO */ + vlc_mutex_lock( &p_fifo->lock ); - /* By construction, the video FIFO cannot be full */ - VIDEO_FIFO_END( *p_fifo ) = p_undec_p; - VIDEO_FIFO_INCEND( *p_fifo ); + /* By construction, the video FIFO cannot be full */ + VIDEO_FIFO_END( *p_fifo ) = p_mb; + VIDEO_FIFO_INCEND( *p_fifo ); - vlc_mutex_unlock( &p_fifo->lock ); - } + vlc_mutex_unlock( &p_fifo->lock ); } /***************************************************************************** - * vpar_ReleasePicture : put a picture in the video_output fifo, and update - * links and buffers + * vpar_ReleaseMacroblock : release a macroblock and put the picture in the + * video output heap, if it is finished *****************************************************************************/ -void vpar_ReleasePicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p ) +void vpar_ReleaseMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb ) { - int i_ref; - - /* Tell referencing pictures so that they can be decoded */ - for( i_ref = 0; p_undec_p->pp_referencing_undec[i_ref].p_undec != NULL - && i_ref < MAX_REFERENCING_UNDEC; i_ref++ ) + /* Unlink referenced pictures */ + if( p_mb->p_forw_top != NULL ) { - *p_undec_p->pp_referencing_undec[i_ref].pp_frame = p_undec_p->p_picture; - vout_LinkPicture( p_fifo->p_vpar.p_vout, p_picture ); - - /* Try to put the referencing picture in the video FIFO */ - vpar_DecodePicture( p_fifo, p_undec_p->pp_referencing_undec[i_ref].p_undec ); + vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_forw_top ); + } + if( p_mb->p_backw_top != NULL ) + { + vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_backw_top ); + } + if( p_mb->p_forw_bot != NULL ) + { + vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_forw_bot ); + } + if( p_mb->p_backw_bot != NULL ) + { + vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_backw_bot ); } - /* Unlink referenced pictures */ - if( p_undec_p->p_forward_ref != NULL ) + /* Unlink picture buffer */ + vlc_mutex_lock( &p_mb->p_picture->lock_deccount ); + p_mb->p_picture->i_deccount--; + if( p_mb->p_picture->i_deccount == 0 ) { - vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_undec_p->p_forward_ref ); - if( p_undec_p->p_backward_ref != NULL ) - { - vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_undec_p->p_backward_ref ); - } + /* Mark the picture to be displayed */ + vout_DisplayPicture( p_fifo->p_vpar.p_vout, p_mb->p_picture ); + + /* Warn Synchro for its records. */ + vpar_SynchroEnd( p_fifo->p_vpar ); } - - /* Mark the picture to be displayed */ - vout_DisplayPicture( p_fifo->p_vpar.p_vout, p_undec_p->p_picture ); + vlc_mutex_unlock( & p_mb->p_picture->lock_deccount ); - /* Release the undec_picture_t structure */ + /* Release the macroblock_t structure */ #define P_buffer p_fifo->p_vpar.vbuffer vlc_mutex_lock( &P_buffer->lock ); - - P_buffer->pp_undec_free[ ++P_buffer->i_index ] = p_undec_p; - + P_buffer->pp_mb_free[ ++P_buffer->i_index ] = p_mb; vlc_mutex_unlock( &P_buffer->lock ); #undef P_buffer - } } /***************************************************************************** - * vpar_DestroyPicture : destroy a picture in case of error + * vpar_DestroyMacroblock : destroy a macroblock in case of error *****************************************************************************/ -void vpar_DestroyPicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p ) +void vpar_DestroyMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb ) { - int i_ref; - - /* Destroy referencing pictures */ - for( i_ref = 0; p_undec_p->pp_referencing_undec[i_ref].p_undec != NULL - && i_ref < MAX_REFERENCING_UNDEC; i_ref++ ) + /* Unlink referenced pictures */ + if( p_mb->p_forw_top != NULL ) { - /* Try to put the referencing picture in the video FIFO */ - vpar_DestroyPicture( p_fifo, p_undec_p->pp_referencing_undec[i_ref].p_undec ); + vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_forw_top ); } - - /* Unlink referenced pictures */ - if( p_undec_p->p_forward_ref != NULL ) + if( p_mb->p_backw_top != NULL ) { - vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_undec_p->p_forward_ref ); - if( p_undec_p->p_backward_ref != NULL ) - { - vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_undec_p->p_backward_ref ); - } + vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_backw_top ); } - - /* Release the picture buffer */ - vout_DestroyPicture( p_fifo->p_vpar.p_vout, p_undec_p->p_picture ); - - /* Release the undec_picture_t structure */ + if( p_mb->p_forw_bot != NULL ) + { + vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_forw_bot ); + } + if( p_mb->p_backw_bot != NULL ) + { + vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_backw_bot ); + } + + /* Release the macroblock_t structure */ #define P_buffer p_fifo->p_vpar.vbuffer vlc_mutex_lock( &P_buffer->lock ); - - P_buffer->pp_undec_free[ ++P_buffer->i_index ] = p_undec_p; - + P_buffer->pp_mb_free[ ++P_buffer->i_index ] = p_mb; vlc_mutex_unlock( &P_buffer->lock ); #undef P_buffer - } } diff --git a/src/video_parser/video_parser.c b/src/video_parser/video_parser.c index b4c0e63988..de98f7fb34 100644 --- a/src/video_parser/video_parser.c +++ b/src/video_parser/video_parser.c @@ -146,6 +146,7 @@ static int CheckConfiguration( video_cfg_t *p_cfg ) *******************************************************************************/ static int InitThread( vpar_thread_t *p_vpar ) { + int i_dummy; intf_DbgMsg("vpar debug: initializing video parser thread %p\n", p_vpar); @@ -181,6 +182,7 @@ static int InitThread( vpar_thread_t *p_vpar ) p_vpar->sequence.nonintra_quant.b_allocated = FALSE; p_vpar->sequence.chroma_intra_quant.b_allocated = FALSE; p_vpar->sequence.chroma_nonintra_quant.b_allocated = FALSE; + p_vpar->sequence.i_frame_number = 0; /* Initialize other properties */ #ifdef STATS @@ -201,16 +203,19 @@ static int InitThread( vpar_thread_t *p_vpar ) bzero( p_vpar->p_vdec, MAX_VDEC*sizeof(vdec_thread_t *) ); - /* Spawn a video_decoder thread */ - /* ??? add the possibility to launch multiple vdec threads */ - if( (p_vpar->p_vdec[0] = vdec_CreateThread( p_vpar )) == NULL ) + /* Spawn video_decoder threads */ + /* ??? modify the number of vdecs at runtime ? */ + for( i_dummy = 0; i_dummy < NB_VDEC; i_dummy++ ) { - return( 1 ); + if( (p_vpar->p_vdec[i_dummy] = vdec_CreateThread( p_vpar )) == NULL ) + { + return( 1 ); + } } /* Mark thread as running and return */ intf_DbgMsg("vpar debug: InitThread(%p) succeeded\n", p_vpar); - return( 0 ); + return( 0 ); } /******************************************************************************* @@ -289,15 +294,16 @@ static void ErrorThread( vpar_thread_t *p_vpar ) vlc_mutex_lock( &p_vpar->fifo.data_lock ); /* ?? trash all trashable PES packets */ - while( !PARSER_FIFO_ISEMPTY(p_vpar->fifo) ) + while( !DECODER_FIFO_ISEMPTY(p_vpar->fifo) ) { - input_NetlistFreePES( p_vpar->bit_stream.p_input, PARSER_FIFO_START(p_vpar->fifo) ); - PARSER_FIFO_INCSTART( p_vpar->fifo ); + input_NetlistFreePES( p_vpar->bit_stream.p_input, + DECODER_FIFO_START(p_vpar->fifo) ); + DECODER_FIFO_INCSTART( p_vpar->fifo ); } vlc_mutex_unlock( &p_vpar->fifo.data_lock ); /* Sleep a while */ - msleep( VPAR_IDLE_SLEEP ); + msleep( VPAR_IDLE_SLEEP ); } } @@ -323,7 +329,7 @@ static void EndThread( vpar_thread_t *p_vpar ) /* ?? */ /* Destroy vdec threads */ - for( i_dummy = 0; i_dummy < MAX_VDEC; i_dummy++ ) + for( i_dummy = 0; i_dummy < NB_VDEC; i_dummy++ ) { if( p_vpar->p_vdec[i_dummy] != NULL ) vdec_DestroyThread( p_vpar->p_vdec[i_dummy] ); diff --git a/src/video_parser/vpar_blocks.c b/src/video_parser/vpar_blocks.c new file mode 100644 index 0000000000..1a2ebbd437 --- /dev/null +++ b/src/video_parser/vpar_blocks.c @@ -0,0 +1,417 @@ +/***************************************************************************** + * vpar_blocks.c : blocks parsing + * (c)1999 VideoLAN + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "common.h" +#include "mtime.h" +#include "vlc_thread.h" + +#include "intf_msg.h" +#include "debug.h" /* ?? temporaire, requis par netlist.h */ + +#include "input.h" +#include "input_netlist.h" +#include "decoder_fifo.h" +#include "video.h" +#include "video_output.h" +#include "video_parser.h" + +#include "video_fifo.h" +#include "video_decoder.h" + +/* + * Local prototypes + */ +static __inline__ void InitMacroblock( vpar_thread_t * p_vpar, + macroblock_t * p_mb, int i_mb_address ); +static __inline__ int MacroblockAddressIncrement( vpar_thread_t * p_vpar ); +static __inline__ void MacroblockModes( vpar_thread_t * p_vpar, + macroblock_t * p_mb ); + +typedef (void *) f_decode_block_t( vpar_thread_t *, macroblock_t *, int ); + +/***************************************************************************** + * vpar_ParseMacroblock : Parse the next macroblock + *****************************************************************************/ +void vpar_ParseMacroblock( vpar_thread_t * p_vpar, int * pi_mb_address, + int i_mb_previous, int i_mb_base ) +{ + static f_addb_t ppf_addb_intra[2] = {vdec_AddBlock, vdec_CopyBlock}; + + int i_mb, i_b, i_mask, i_x, i_y, pi_pos[3], pi_width[3]; + macroblock_t * p_mb; + f_addb_t pf_addb; + + *pi_mb_address += MacroblockAddressIncrement( p_vpar ); + + for( i_mb = i_mb_previous; i_mb < *pi_mb_address; i_mb++ ) + { + /* Skipped macroblock (ISO/IEC 13818-2 7.6.6). */ + static int pi_dc_dct_reinit[4] = {128,256,512,1024}; + static f_motion_t pf_motion_skipped[4] = {NULL, vdec_MotionField, + vdec_MotionField, vdec_MotionFrame}; + + /* Reset DC predictors (7.2.1). */ + p_vpar->slice.pi_dct_pred[0] = p_vpar->slice.pi_dct_pred[1] + = p_vpar->slice.pi_dct_pred[2] + = pi_dc_dct_reinit[p_vpar->picture.i_intra_dc_precision]; + + if( p_vpar->picture.i_coding_type == P_CODING_TYPE ) + { + /* Reset motion vector predictors (ISO/IEC 13818-2 7.6.3.4). */ + bzero( p_vpar->slice.pppi_pmv, 8*sizeof(int) ); + } + + if( (p_mb = p_vpar->picture.pp_mb[i_mb_base + i_mb] = + vpar_NewMacroblock( &p_vpar->vfifo )) == NULL ) + { + p_vpar->picture.b_error = TRUE; + intf_ErrMsg("vpar error: macroblock list is empty !"); + return; + } + + InitMacroblock( p_vpar, p_mb, i_mb ); + + /* No IDCT nor AddBlock. */ + for( i_b = 0; i_b < 12; i_b++ ) + { + p_mb->pf_idct[i_b] = vdec_DummyIDCT; + p_mb->pf_addb[i_b] = vdec_DummyBlock; + } + + /* Motion type is picture structure. */ + p_mb->pf_motion = pf_motion_skipped[p_vpar->picture.i_structure]; + + /* Predict from field of same parity. */ + /* ??? */ + } + + /* Get a macroblock structure. */ + if( (p_mb = p_vpar->picture.pp_mb[i_mb_base + *pi_mb_address] = + vpar_NewMacroblock( &p_vpar->vfifo )) == NULL ) + { + p_vpar->picture.b_error = TRUE; + intf_ErrMsg("vpar error: macroblock list is empty !"); + return; + } + + InitMacroblock( p_vpar, p_mb, *pi_mb_address ); + + /* Parse off macroblock_modes structure. */ + MacroblockModes( p_vpar, p_mb ); + + if( p_vpar->mb.i_mb_type & MB_QUANT ) + { + LoadQuantizerScale( p_vpar ); + } + + if( p_vpar->mb.i_mb_type & MB_MOTION_FORWARD ) + { + (*p_vpar->sequence.pf_decode_mv)( p_vpar, 0 ); + } + + if( p_vpar->mb.i_mb_type & MB_MOTION_BACKWARD ) + { + (*p_vpar->sequence.pf_decode_mv)( p_vpar, 1 ); + } + + if( p_vpar->picture.b_concealment_mv && (p_vpar->mb.i_mb_type & MB_INTRA) ) + { + DumpBits( &p_vpar->bit_stream, 1 ); + } + + if( p_vpar->mb.i_mb_type & MB_PATTERN ) + { + (*p_vpar->sequence.pf_decode_pattern)( p_vpar ); + } + else + { + int pi_coded_block_pattern[2] = {0, + (1 << 4+2*p_vpar->sequence.i_chroma_nb_blocks) - 1}; + p_vpar->mb.i_coded_block_pattern = pi_coded_block_pattern + [p_vpar->mb.i_mb_type & MB_INTRA]; + } + + pf_addb = ppf_addb_intra[p_vpar->mb.i_mb_type & MB_INTRA]; + + /* C'est de la merde, il faut recommencer */ + + i_x = p_mb->i_mb_x << 4; + i_y = p_mb->i_mb_y << 4; + + pi_pos[0] = i_y*(p_vpar->sequence.i_width + << (!p_vpar->picture.b_frame_structure)) + + (p_mb->i_structure == BOTTOM_FIELD)*p_vpar->sequence.i_width + + i_x; + pi_pos[1] = pi_pos[2] = i_y*(p_vpar->sequence.i_chroma_width + << (!p_vpar->picture.b_frame_structure)) + + (p_mb->i_structure == BOTTOM_FIELD)*p_vpar->sequence.i_chroma_width + + (i_x >> (3-p_vpar->sequence.i_chroma_format)); + pi_width[0] = p_vpar->sequence.i_width << (!p_vpar->picture.b_frame_structure + || p_vpar->mb.b_dct_type); + pi_width[1] = pi_width[2] = p_vpar->sequence.i_chroma_width + << (!p_vpar->picture.b_frame_structure || p_vpar->mb.b_dct_type); + + /* Effectively decode blocks. */ + for( i_b = 0, i_mask = 1 << (3 + 2*p_vpar->sequence.i_chroma_nb_blocks); + i_b < 4 + 2*p_vpar->sequence.i_chroma_nb_blocks; i_b++, i_mask >>= 1 ) + { + if( p_vpar->mb.i_coded_block_pattern & i_mask ) + { + static f_decode_block_t pppf_decode_block[2][2] = + { {vpar_DecodeMPEG1Non, vpar_DecodeMPEG1Intra}, + {vpar_DecodeMPEG2Non, vpar_DecodeMPEG2Intra} }; + static int pi_x[12] = {0,8,0,8,0,0,0,0,8,8,8,8}; + static int pi_y[12] = {0,0,8,8,0,0,8,8,0,0,8,8}; + data_t pi_data[12] = + {p_mb->p_picture->p_y, p_mb->p_picture->p_y, + p_mb->p_picture->p_y, p_mb->p_picture->p_y, + p_mb->p_picture->p_u, p_mb->p_picture->p_v, + p_mb->p_picture->p_u, p_mb->p_picture->p_v, + p_mb->p_picture->p_u, p_mb->p_picture->p_v, + p_mb->p_picture->p_u, p_mb->p_picture->p_v}; + + bzero( p_mb->ppi_blocks[i_b], 64*sizeof(elem_t) ); + (*pppf_decode_block[p_vpar->sequence.b_mpeg2] + [p_vpar->mb.i_mb_type & MB_INTRA]) + ( p_vpar, p_mb, i_b ); + + /* decode_block has already set pf_idct and pi_sparse_pos. */ + p_mb->pf_addb[i_b] = pf_addb; + + /* Calculate block coordinates. */ + p_mb->p_data[i_b] = pi_data[i_b] + pi_pos[i_b >> 2] + + pi_y[i_b]*pi_width[i_b >> 2] + + (p_vpar->mb.b_dct_type & ((i_b & 2) >> 1)) + /* INACHEVÉ parce que trop pourri ! */ + } + else + { + /* Block not coded, so no IDCT, nor AddBlock */ + p_mb->pf_addb[i_b] = vdec_DummyBlock; + p_mb->pf_idct[i_b] = vdec_DummyIDCT; + } + } + + if( !( p_vpar->mb.i_mb_type & MB_INTRA ) ) + { + static int pi_dc_dct_reinit[4] = {128,256,512,1024}; + + /* Reset DC predictors (7.2.1). */ + p_vpar->slice.pi_dct_pred[0] = p_vpar->slice.pi_dct_pred[1] + = p_vpar->slice.pi_dct_pred[2] + = pi_dc_dct_reinit[p_vpar->picture.i_intra_dc_precision]; + } + else if( !p_vpar->picture.b_concealment_mv ) + { + /* Reset MV predictors. */ + bzero( p_vpar->slice.pppi_pmv, 8*sizeof(int) ); + } + + if( (p_vpar->picture.i_coding_type == P_CODING_TYPE) && + !(p_vpar->mb.i_mb_type & (MB_MOTION_FORWARD|MB_INTRA)) ) + { + /* Special No-MC macroblock in P pictures (7.6.3.5). */ + p_vpar->slice.pppi_pmv[0][0][0] = p_vpar->slice.pppi_pmv[0][0][1] = + p_vpar->slice.pppi_pmv[1][0][0] = p_vpar->slice.pppi_pmv[1][0][1] = 0; + + /* motion type ?????? */ + /* predict from field of same parity ????? */ + } +} + +/***************************************************************************** + * InitMacroblock : Initialize macroblock values + *****************************************************************************/ +static __inline__ void InitMacroblock( vpar_thread_t * p_vpar, + macroblock_t * p_mb, int i_mb_address ) +{ + p_mb->p_picture = p_vpar->picture.p_picture; + p_mb->i_structure = p_vpar->picture.i_structure; + p_mb->i_mb_x = i_mb_address % p_vpar->sequence.i_mb_width; + p_mb->i_mb_y = i_mb_address / p_vpar->sequence.i_mb_width; + p_mb->i_chroma_nb_blocks = p_vpar->sequence.i_chroma_nb_blocks; + + p_mb->i_lum_incr = p_vpar->picture.i_lum_incr; + p_mb->i_chroma_incr = p_vpar->picture.i_chroma_incr; +} + +/***************************************************************************** + * MacroblockAddressIncrement : Get the macroblock_address_increment field + *****************************************************************************/ +static __inline__ int MacroblockAddressIncrement( vpar_thread_t * p_vpar ) +{ + /* À pomper dans Berkeley */ +} + +/***************************************************************************** + * MacroblockModes : Get the macroblock_modes structure + *****************************************************************************/ +static __inline__ void MacroblockModes( vpar_thread_t * p_vpar, + macroblock_t * p_mb ) +{ + static f_motion_t pf_motion[2][4] = + { {NULL, vdec_FieldRecon, vdec_16x8Recon, vdec_DMVRecon}, + {NULL, vdec_FieldRecon, vdec_FrameRecon, vdec_DMVRecon} }; + static int ppi_mv_count[2][4] = { {0, 1, 2, 1}, {0, 2, 1, 1} }; + static int ppi_mv_format[2][4] = { {0, 1, 1, 1}, {0, 1, 2, 1} }; + + /* Get macroblock_type. */ + p_vpar->mb.i_mb_type = (*p_vpar->picture.pf_macroblock_type) + ( vpar_thread_t * p_vpar ); + + /* SCALABILITY : warning, we don't know if spatial_temporal_weight_code + * has to be dropped, take care if you use scalable streams. */ + /* DumpBits( &p_vpar->bit_stream, 2 ); */ + + if( !(p_vpar->mb.i_mb_type & (MB_MOTION_FORWARD | MB_MOTION_BACKWARD)) + || p_vpar->picture.b_frame_pred_frame_dct ) + { + /* If mb_type has neither MOTION_FORWARD nor MOTION_BACKWARD, this + * is useless, but also harmless. */ + p_vpar->mb.i_motion_type = MOTION_FRAME; + } + else + { + p_vpar->mb.i_motion_type = GetBits( &p_vpar->bit_stream, 2 ); + } + + p_mb->f_motion = pf_motion[p_vpar->picture.b_frame_structure] + [p_vpar->mb.i_motion_type]; + p_vpar->mb.i_mv_count = ppi_mv_count[p_vpar->picture.b_frame_structure] + [p_vpar->mb.i_motion_type]; + p_vpar->mb.i_mv_format = ppi_mv_format[p_vpar->picture.b_frame_structure] + [p_vpar->mb.i_motion_type]; + + if( (p_vpar->picture.i_structure == FRAME_STRUCTURE) && + (!p_vpar->picture.b_frame_pred_frame_dct) && + (p_var->mb.i_mb_type & (MB_PATTERN|MB_INTRA)) ) + { + p_vpar->mb.b_dct_type = GetBits( &p_vpar->bit_stream, 1 ); + } + else + { + p_vpar->mb.b_dct_type = 0; + } +} + +/***************************************************************************** + * vpar_IMBType : macroblock_type in I pictures + *****************************************************************************/ +int vpar_IMBType( vpar_thread_t * p_vpar ) +{ + /* À pomper dans Berkeley */ +} + +/***************************************************************************** + * vpar_PMBType : macroblock_type in P pictures + *****************************************************************************/ +int vpar_PMBType( vpar_thread_t * p_vpar ) +{ + /* À pomper dans Berkeley */ +} + +/***************************************************************************** + * vpar_BMBType : macroblock_type in B pictures + *****************************************************************************/ +int vpar_BMBType( vpar_thread_t * p_vpar ) +{ + /* À pomper dans Berkeley */ +} + +/***************************************************************************** + * vpar_DMBType : macroblock_type in D pictures + *****************************************************************************/ +int vpar_DMBType( vpar_thread_t * p_vpar ) +{ + /* À pomper dans Berkeley */ +} + +/***************************************************************************** + * vpar_CodedPattern420 : coded_block_pattern with 420 chroma + *****************************************************************************/ +int vpar_CodedPattern420( vpar_thread_t * p_vpar ) +{ + /* À pomper dans Berkeley */ +} + +/***************************************************************************** + * vpar_CodedPattern422 : coded_block_pattern with 422 chroma + *****************************************************************************/ +int vpar_CodedPattern422( vpar_thread_t * p_vpar ) +{ + /* À pomper dans Berkeley + attention ! y'a 2 bits en plus en MPEG2 */ +} + +/***************************************************************************** + * vpar_CodedPattern444 : coded_block_pattern with 444 chroma + *****************************************************************************/ +int vpar_CodedPattern444( vpar_thread_t * p_vpar ) +{ + /* À pomper dans Berkeley + attention ! y'a 4 bits en plus en MPEG2 */ +} + +/***************************************************************************** + * vpar_DecodeMPEG1Non : decode MPEG-1 non-intra blocks + *****************************************************************************/ +void vpar_DecodeMPEG1Non( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_b ) +{ + /* À pomper dans Berkeley. Pour toutes ces fonctions, il faut mettre + p_mb->pf_idct[i_b] à : + - vdec_IDCT ou + - vdec_SparseIDCT si la matrice n'a qu'un coefficient non nul. + Dans le deuxième cas, p_mb->pi_sparse_pos[i_b] contient le numéro + de ce coefficient. */ + + if( p_vpar->picture.i_coding_type == D_CODING_TYPE ) + { + /* Remove end_of_macroblock (always 1, prevents startcode emulation) + * ISO/IEC 11172-2 section 2.4.2.7 and 2.4.3.6 */ + DumpBits( &p_vpar->fifo, 1 ); + } +} + +/***************************************************************************** + * vpar_DecodeMPEG1Intra : decode MPEG-1 intra blocks + *****************************************************************************/ +void vpar_DecodeMPEG1Intra( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_b ) +{ + /* À pomper dans Berkeley. */ + + if( p_vpar->picture.i_coding_type == D_CODING_TYPE ) + { + /* Remove end_of_macroblock (always 1, prevents startcode emulation) + * ISO/IEC 11172-2 section 2.4.2.7 and 2.4.3.6 */ + DumpBits( &p_vpar->fifo, 1 ); + } +} + +/***************************************************************************** + * vpar_DecodeMPEG2Non : decode MPEG-2 non-intra blocks + *****************************************************************************/ +void vpar_DecodeMPEG2Non( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_b ) +{ + /* À pomper dans Berkeley. Bien sûr les matrices seront différentes... */ +} + +/***************************************************************************** + * vpar_DecodeMPEG2Intra : decode MPEG-2 intra blocks + *****************************************************************************/ +void vpar_DecodeMPEG2Intra( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_b ) +{ + /* À pomper dans Berkeley. */ +} diff --git a/src/video_parser/vpar_headers.c b/src/video_parser/vpar_headers.c index 7c022ad4a5..7af83a8a16 100644 --- a/src/video_parser/vpar_headers.c +++ b/src/video_parser/vpar_headers.c @@ -3,8 +3,6 @@ * (c)1999 VideoLAN *****************************************************************************/ -/* ?? passer en terminate/destroy avec les signaux supplémentaires */ - /***************************************************************************** * Preamble *****************************************************************************/ @@ -30,15 +28,41 @@ #include "decoder_fifo.h" #include "video.h" #include "video_output.h" +#include "vpar_blocks.h" #include "video_parser.h" -#include "undec_picture.h" +#include "macroblock.h" #include "video_fifo.h" #include "video_decoder.h" /* * Local prototypes */ +static __inline__ void NextStartCode( vpar_thread_t * p_vpar ); +static void GroupHeader( vpar_thread_t * p_vpar ) +static void PictureHeader( vpar_thread_t * p_vpar ) +static void __inline__ ReferenceUpdate( 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 ) +static void SliceHeader00( vpar_thread_t * p_vpar, + int * pi_mb_address, int i_mb_base, + elem_t * p_y, p_u, p_v, u32 i_vert_code ) +static void SliceHeader01( vpar_thread_t * p_vpar, + int * pi_mb_address, int i_mb_base, + elem_t * p_y, p_u, p_v, u32 i_vert_code ) +static void SliceHeader10( vpar_thread_t * p_vpar, + int * pi_mb_address, int i_mb_base, + elem_t * p_y, p_u, p_v, u32 i_vert_code ) +static void SliceHeader11( vpar_thread_t * p_vpar, + int * pi_mb_address, int i_mb_base, + elem_t * p_y, p_u, p_v, u32 i_vert_code ) +static __inline__ void SliceHeader( vpar_thread_t * p_vpar, + int * pi_mb_address, int i_mb_base, + elem_t * p_y, p_u, p_v, u32 i_vert_code ) +static void ExtensionAndUserData( vpar_thread_t * p_vpar ) /***************************************************************************** * vpar_NextSequenceHeader : Find the next sequence header @@ -98,7 +122,7 @@ int vpar_ParseHeader( vpar_thread_t * p_vpar ) *****************************************************************************/ static __inline__ void NextStartCode( vpar_thread_t * p_vpar ) { - /* Re-align the buffer to an 8-bit boundary */ + /* Re-align the buffer on an 8-bit boundary */ DumpBits( &p_vpar->bit_stream, p_vpar->bit_stream.fifo.i_available & 7 ); while( ShowBits( &p_vpar->bit_stream, 24 ) != 0x01L && !p_vpar->b_die ) @@ -110,37 +134,31 @@ static __inline__ void NextStartCode( vpar_thread_t * p_vpar ) /***************************************************************************** * SequenceHeader : Parse the next sequence header *****************************************************************************/ -#define RESERVED -1 -static double d_frame_rate_table[16] = -{ - 0.0, - ((23.0*1000.0)/1001.0), - 24.0, - 25.0, - ((30.0*1000.0)/1001.0), - 30.0, - 50.0, - ((60.0*1000.0)/1001.0), - 60.0, - - RESERVED, - RESERVED, - RESERVED, - RESERVED, - RESERVED, - RESERVED, - RESERVED -}; - static void SequenceHeader( vpar_thread_t * p_vpar ) { +#define RESERVED -1 + static double d_frame_rate_table[16] = + { + 0.0, + ((23.0*1000.0)/1001.0), + 24.0, + 25.0, + ((30.0*1000.0)/1001.0), + 30.0, + 50.0, + ((60.0*1000.0)/1001.0), + 60.0, + RESERVED, RESERVED, RESERVED, RESERVED, RESERVED, RESERVED, RESERVED + }; +#undef RESERVED + int i_height_save, i_width_save; i_height_save = p_vpar->sequence.i_height; i_width_save = p_vpar->sequence.i_width; - p_vpar->sequence.i_height = ntohl( GetBits( p_vpar->bit_stream, 12 ) ); - p_vpar->sequence.i_width = ntohl( GetBits( p_vpar->bit_stream, 12 ) ); + p_vpar->sequence.i_height = GetBits( p_vpar->bit_stream, 12 ); + p_vpar->sequence.i_width = GetBits( p_vpar->bit_stream, 12 ); p_vpar->sequence.i_ratio = GetBits( p_vpar->bit_stream, 4 ); p_vpar->sequence.d_frame_rate = d_frame_rate_table( GetBits( p_vpar->bit_stream, 4 ) ); @@ -182,9 +200,14 @@ static void SequenceHeader( vpar_thread_t * p_vpar ) /* * Sequence Extension */ - if( ShowBits( p_vpar->bit_stream, 32 ) == EXTENSION_START_CODE ) + NextStartCode( p_vpar ); + if( ShowBits( &p_vpar->bit_stream, 32 ) == EXTENSION_START_CODE ) { int i_dummy; + static int pi_chroma_nb_blocks[4] = {0, 1, 2, 4}; + static (void *) ppf_chroma_pattern[4]( vpar_thread_t * ) = + {NULL, vpar_CodedPattern420, + vpar_CodedPattern422, vpar_CodedPattern444}; /* Parse sequence_extension */ DumpBits32( &p_vpar->bit_stream ); @@ -192,6 +215,12 @@ static void SequenceHeader( vpar_thread_t * p_vpar ) DumpBits( &p_vpar->bit_stream, 12 ); p_vpar->sequence.b_progressive = GetBits( &p_vpar->bit_stream, 1 ); p_vpar->sequence.i_chroma_format = GetBits( &p_vpar->bit_stream, 2 ); + p_vpar->sequence.i_chroma_width = p_vpar->sequence.i_width + >> (3-p_vpar->sequence.i_chroma_format); + p_vpar->sequence.i_chroma_nb_blocks = pi_chroma_nb_blocks + [p_vpar->sequence.i_chroma_format]; + p_vpar->sequence.pf_decode_pattern = ppf_chroma_pattern + [p_vpar->sequence.i_chroma_format]; p_vpar->sequence.i_width |= GetBits( &p_vpar->bit_stream, 2 ) << 12; p_vpar->sequence.i_height |= GetBits( &p_vpar->bit_stream, 2 ) << 12; /* bit_rate_extension, marker_bit, vbv_buffer_size_extension, low_delay */ @@ -202,180 +231,64 @@ static void SequenceHeader( vpar_thread_t * p_vpar ) p_vpar->sequence.d_frame_rate *= (i_dummy + 1) / (GetBits( &p_vpar->bit_stream, 5 ) + 1); - /* Extension and User data */ - ExtensionAndUserData( p_vpar ); + p_vpar->sequence.pf_decode_mv = vpar_MPEG2MotionVector; } else { /* It's an MPEG-1 stream. Put adequate parameters. */ p_vpar->sequence.b_progressive = 1; - p_vpar->i_chroma_format = CHROMA_420; + p_vpar->sequence.i_chroma_format = CHROMA_420; + p_vpar->sequence.i_chroma_width = p_vpar->sequence.i->width >> 2; + p_vpar->sequence.i_chroma_nb_blocks = 2; + p_vpar->sequence.pf_decode_pattern = vpar_CodedPattern420; + + p_vpar->sequence.pf_decode_mv = vpar_MPEG1MotionVector; } p_vpar->sequence.i_mb_width = (p_vpar->sequence.i_width + 15) / 16; p_vpar->sequence.i_mb_height = (p_vpar->sequence.b_progressive) ? (p_vpar->sequence.i_height + 15) / 16 : 2 * (p_vpar->sequence.i_height + 31) / 32; + p_vpar->sequence.i_mb_size = p_vpar->sequence.i_mb_width + * p_vpar->sequence.i_mb_height; p_vpar->sequence.i_width = (p_vpar->sequence.i_mb_width * 16); p_vpar->sequence.i_height = (p_vpar->sequence.i_mb_height * 16); + p_vpar->sequence.i_size = p_vpar->sequence.i_width + * p_vpar->sequence.i_height; - if( p_vpar->sequence.i_width != i_width_save - || p_vpar->sequence.i_height != i_height_save - || p_vpar->sequence.p_frame_lum_lookup == NULL ) + /* Slice Header functions */ + if( p_vpar->sequence.i_height <= 2800 ) { - int i_x, i_y; - pel_lookup_table * p_fr, p_fl; - int i_fr, i_fl; - static int pi_chroma_size[4] = {0, 2, 1, 0} -#define Sequence p_vpar->sequence - - /* The size of the pictures has changed. Probably a new sequence. - * We must recalculate the lookup matrices. */ - - /* First unlink the previous lookup matrices so that they can - * be freed in the future. */ - if( Sequence.p_frame_lum_lookup != NULL ) + if( p_vpar->sequence.i_scalable_mode != SC_DP ) { - UNLINK_LOOKUP( Sequence.p_frame_lum_lookup ); - UNLINK_LOOKUP( Sequence.p_field_lum_lookup ); - UNLINK_LOOKUP( Sequence.p_frame_chroma_lookup ); - UNLINK_LOOKUP( Sequence.p_field_chroma_lookup ); + p_vpar->sequence.pf_slice_header = SliceHeader00; } - - /* Allocate the new lookup tables. */ - Sequence.p_frame_lum_lookup - = (pel_lookup_table_t *)malloc( sizeof( pel_lookup_table_t ) * - Sequence.i_width * Sequence.i_height ); - Sequence.p_field_lum_lookup - = (pel_lookup_table_t *)malloc( sizeof( pel_lookup_table_t ) * - Sequence.i_width * Sequence.i_height ); - Sequence.p_frame_chroma_lookup - = (pel_lookup_table_t *)malloc( sizeof( pel_lookup_table_t ) * - Sequence.i_width * Sequence.i_height - >> pi_chroma_size[Sequence.i_chroma_format] ); - Sequence.p_field_chroma_lookup - = (pel_lookup_table_t *)malloc( sizeof( pel_lookup_table_t ) * - Sequence.i_width * Sequence.i_height - >> pi_chroma_size[Sequence.i_chroma_format] ); - - if( !Sequence.p_frame_lum_lookup || !Sequence.p_field_lum_lookup - || !Sequence.p_frame_chroma_lookup - || !Sequence.p_field_chroma_lookup ) + else { - intf_DbgMsg("vpar error: not enough memory for lookup tables"); - p_vpar->b_error = 1; - return; + p_vpar->sequence.pf_slice_header = SliceHeader01; } - - /* Fill in the luminance lookup tables */ - p_fr = &Sequence.p_frame_lum_lookup->pi_pel; - p_fl = &Sequence.p_field_lum_lookup->pi_pel; - i_fr = i_fl = 0; - - for( i_y = 0; i_y < Sequence.i_height; i_y++ ) + } + else + { + if( p_vpar->sequence.i_scalable_mode != SC_DP ) { - int i_mb_y, i_b_y, i_pos_y; - i_mb_y = i_y >> 4; - i_b_y = (i_y & 15) >> 3; - i_pos_y = (i_y & 7); - - for( i_x = 0; i_x < Sequence.i_width; i_x++ ) - { - int i_mb_x, i_b_x, i_pos_x; - i_mb_x = i_x >> 4; - i_b_x = (i_x & 15) >> 3; - i_pos_x = (i_x & 7); - - p_fl[i_fr + i_x] = p_fr[i_fr + i_x] - = (i_mb_y*Sequence.i_mb_width + i_mb_y)*256 - + ((i_b_y << 1) + i_b_x)*64 - + i_pos_y*8 + i_pos_x; - } - i_fr += Sequence.i_width; - i_fl += Sequence.i_width << 1; - if( i_fl == Sequence.i_width*Sequence.i_height ) - { - i_fl = Sequence.i_width; - } + p_vpar->sequence.pf_slice_header = SliceHeader10; } - - /* Fill in the chrominance lookup tables */ - p_fr = &Sequence.p_frame_chroma_lookup->pi_pel; - p_fl = &Sequence.p_field_chroma_lookup->pi_pel; - i_fr = i_fl = 0; - - switch( p_vpar->i_chroma_format ) + else { - case CHROMA_444: - /* That's the same as luminance */ - memcopy( &Sequence.p_frame_croma_lookup->pi_pel, - &Sequence.p_frame_lum_lookup->pi_pel, - sizeof(PEL_P)*Sequence.i_height*Sequence.i_width ); - memcopy( &Sequence.p_field_croma_lookup->pi_pel, - &Sequence.p_field_lum_lookup->pi_pel, - sizeof(PEL_P)*Sequence.i_height*Sequence.i_width ); - - case CHROMA_422: - for( i_y = 0; i_y < Sequence.i_height; i_y++ ) - { - int i_mb_y, i_b_y, i_pos_y; - i_mb_y = i_y >> 4; - i_b_y = (i_y & 15) >> 3; - i_pos_y = (i_y & 7); - - for( i_x = 0; i_x < (Sequence.i_width >> 1); i_x++ ) - { - int i_mb_x, i_pos_x; - i_mb_x = i_x >> 3; - i_pos_x = (i_x & 7); - - p_fl[i_fr + i_x] = p_fr[i_fr + i_x] - = (i_mb_y*Sequence.i_mb_width + i_mb_y)*128 - + i_b_y*64 - + i_pos_y*8 + i_pos_x; - } - i_fr += Sequence.i_width >> 1; - i_fl += Sequence.i_width; - if( i_fl == (Sequence.i_width*Sequence.i_height >> 1) ) - { - i_fl = (Sequence.i_width >> 1); - } - } + p_vpar->sequence.pf_slice_header = SliceHeader11; + } + } + + if( p_vpar->sequence.i_width != i_width_save + || p_vpar->sequence.i_height != i_height_save + || p_vpar->sequence.p_frame_lum_lookup == NULL ) + { - case CHROMA_420: - for( i_y = 0; i_y < (Sequence.i_height >> 1); i_y++ ) - { - int i_mb_y, i_pos_y; - i_mb_y = i_y >> 3; - i_pos_y = (i_y & 7); - - for( i_x = 0; i_x < (Sequence.i_width >> 1); i_x++ ) - { - int i_mb_x, i_pos_x; - i_mb_x = i_x >> 3; - i_pos_x = (i_x & 7); - - p_fl[i_fr + i_x] = p_fr[i_fr + i_x] - = (i_mb_y*Sequence.i_mb_width + i_mb_y)*64 - + i_pos_y*8 + i_pos_x; - } - i_fr += Sequence.i_width >> 1; - i_fl += Sequence.i_width; - if( i_fl == (Sequence.i_width*Sequence.i_height >> 2) ) - { - i_fl = Sequence.i_width >> 1; - } - } - } /* switch */ - - /* Link the new lookup tables so that they don't get freed all - * the time. */ - LINK_LOOKUP( Sequence.p_frame_lum_lookup ); - LINK_LOOKUP( Sequence.p_field_lum_lookup ); - LINK_LOOKUP( Sequence.p_frame_chroma_lookup ); - LINK_LOOKUP( Sequence.p_field_chroma_lookup ); -#undef Sequence } + + /* Extension and User data */ + ExtensionAndUserData( p_vpar ); } /***************************************************************************** @@ -393,57 +306,233 @@ static void GroupHeader( vpar_thread_t * p_vpar ) *****************************************************************************/ static void PictureHeader( vpar_thread_t * p_vpar ) { - int i_coding_type; - mtime_t i_pts; - undec_picture_t * p_undec_p; + static (int *) ppf_macroblock_type[4] = {vpar_IMBType, vpar_PMBType, + vpar_BMBType, vpar_DMBType}; + + int i_structure; + int i_mb_address, i_mb_base, i_mb; + elem_t * p_y, p_u, p_v; + boolean_t b_parsable; + u32 i_dummy; DumpBits( &p_vpar->bit_stream, 10 ); /* temporal_reference */ - i_coding_type = GetBits( &p_vpar->bit_stream, 3 ); + p_vpar->picture.i_coding_type = GetBits( &p_vpar->bit_stream, 3 ); + p_vpar->picture.pf_macroblock_type = ppf_macroblock_type + [p_vpar->picture.i_coding_type]; + + DumpBits( &p_vpar->bit_stream, 16 ); /* vbv_delay */ - if( ((i_coding_type == P_CODING_TYPE) && - (p_vpar->sequence.p_forward == NULL)) || - ((i_coding_type == B_CODING_TYPE) && - (p_vpar->sequence.p_forward == NULL || - p_vpar->sequence.p_backward == NULL)) ) - { - /* The picture cannot be decoded because we lack one of the - * reference frames */ + p_vpar->picture.b_full_pel_forward_vector = GetBits( &p_vpar->bit_stream, 1 ); + p_vpar->picture.i_forward_f_code = GetBits( &p_vpar->bit_stream, 3 ); + p_vpar->picture.b_full_pel_backward_vector = GetBits( &p_vpar->bit_stream, 1 ); + p_vpar->picture.i_backward_f_code = GetBits( &p_vpar->bit_stream, 3 ); + + /* extra_information_picture */ + while( GetBits( &p_vpar->bit_stream, 1 ) ) + { + DumpBits( &p_vpar->bit_stream, 8 ); + } + + /* + * Picture Coding Extension + */ + NextStartCode( p_vpar ); + if( ShowBits( &p_vpar->bit_stream, 32 ) == EXTENSION_START_CODE ) + { + /* Parse picture_coding_extension */ + DumpBits32( &p_vpar->bit_stream ); + /* extension_start_code_identifier */ + DumpBits( &p_vpar->bit_stream, 4 ); - /* Update the reference pointers */ - ReferenceUpdate( p_vpar, i_coding_type, NULL ); + p_vpar->picture.ppi_f_code[0][0] = GetBits( &p_vpar->bit_stream, 4 ); + p_vpar->picture.ppi_f_code[0][1] = GetBits( &p_vpar->bit_stream, 4 ); + p_vpar->picture.ppi_f_code[1][0] = GetBits( &p_vpar->bit_stream, 4 ); + p_vpar->picture.ppi_f_code[1][1] = GetBits( &p_vpar->bit_stream, 4 ); + p_vpar->picture.i_intra_dc_precision = GetBits( &p_vpar->bit_stream, 2 ); + i_structure = GetBits( &p_vpar->bit_stream, 2 ); + p_vpar->picture.b_top_field_first = GetBits( &p_vpar->bit_stream, 1 ); + p_vpar->picture.b_frame_pred_frame_dct + = GetBits( &p_vpar->bit_stream, 1 ); + p_vpar->picture.b_concealment_mv = GetBits( &p_vpar->bit_stream, 1 ); + p_vpar->picture.b_q_scale_type = GetBits( &p_vpar->bit_stream, 1 ); + p_vpar->picture.b_intra_vlc_format = GetBits( &p_vpar->bit_stream, 1 ); + p_vpar->picture.b_alternate_scan = GetBits( &p_vpar->bit_stream, 1 ); + /* repeat_first_field (ISO/IEC 13818-2 6.3.10 is cryptic and + * apparently the reference decoder doesn't use it, so trash it), + * chroma_420_type (obsolete) */ + DumpBits( &p_vpar->bit_stream, 2 ); + p_vpar->picture.b_progressive_frame = GetBits( &p_vpar->bit_stream, 1 ); - /* Warn Synchro we have trashed a picture */ - vpar_SynchroTrash( p_vpar, i_coding_type ); - - return; + /* composite_display_flag */ + if( GetBits( &p_vpar->bit_stream, 1 ) ) + { + /* v_axis, field_sequence, sub_carrier, burst_amplitude, + * sub_carrier_phase */ + DumpBits( &p_vpar->bit_stream, 20 ); + } + } + else + { + /* MPEG-1 compatibility flags */ + p_vpar->i_intra_dc_precision = 0; /* 8 bits */ + i_structure = FRAME_STRUCTURE; + p_vpar->b_frame_pred_frame_dct = TRUE; + p_vpar->picture.b_concealment_mv = 0; + p_vpar->picture.b_q_scale_type = 0; + p_vpar->picture.b_intra_vlc_format = 0; + p_vpar->picture.b_alternate_scan = 0; /* zigzag */ + b_repeat_first_field = FALSE; + p_vpar->picture.b_progressive_frame = TRUE; } - if( !(i_pts = vpar_SynchroChoose( p_vpar, i_coding_type )) ) + if( p_vpar->picture.i_current_structure && + (i_structure == FRAME_STRUCTURE || + i_structure == p_vpar->picture.i_current_structure) ) { - /* Synchro has decided not to decode the picture */ + /* We don't have the second field of the buffered frame. */ + if( p_pvar->picture.p_picture != NULL ) + { + ReferenceReplace( p_vpar, + p_vpar->picture.p_second_field_buffer->i_coding_type, + NULL ); + + for( i_mb = 0; i_mb < p_vpar->sequence.i_mb_size >> 1; i_mb++ ) + { + vpar_DestroyMacroblock( &p_vpar->vfifo, + p_vpar->picture.pp_mb[i_mb] ); + } + vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture ); + } - /* Update the reference pointers */ + p_pvar->picture.i_current_structure = 0; + + intf_DbgMsg("vpar debug: odd number of field picture."); + } + + if( p_vpar->picture.i_current_structure ) + { + /* Second field of a frame. We will decode it if, and only if we + * have decoded the first frame. */ + b_parsable = (p_vpar->picture.p_second_field_buffer != NULL); + } + else + { + /* Do we have the reference pictures ? */ + b_parsable = !((i_coding_type == P_CODING_TYPE) && + (p_vpar->sequence.p_forward == NULL)) || + ((i_coding_type == B_CODING_TYPE) && + (p_vpar->sequence.p_forward == NULL || + p_vpar->sequence.p_backward == NULL)); + + /* Does synchro say we have enough time to decode it ? */ + b_parsable &&= vpar_SynchroChoose( p_vpar, i_coding_type, i_structure ); + } + + if( !b_parsable ) + { + /* Update the reference pointers. */ ReferenceUpdate( p_vpar, i_coding_type, NULL ); + /* Warn Synchro we have trashed a picture. */ + vpar_SynchroTrash( p_vpar, i_coding_type, i_structure ); + + /* Update context. */ + if( i_structure != FRAME_STRUCTURE ) + p_vpar->picture.i_current_structure = i_structure; + p_vpar->picture.p_picture = NULL; + return; } - /* OK, now we are sure we will decode the picture. Get a structure. */ - p_undec_p = vpar_NewPicture( &p_vpar->vfifo ); - - /* Request a buffer from the video_output. */ - p_undec_p->p_picture = vout_CreatePicture( p_vpar->p_vout, - SPLITTED_YUV_PICTURE, - p_vpar->sequence.i_width, - p_vpar->sequence.i_height, - p_vpar->sequence.i_chroma_format ); - - /* Initialize values */ - p_undec_p->i_coding_type = i_conding_type; - p_undec_p->b_mpeg2 = p_vpar->sequence.b_mpeg2; - p_undec_p->i_mb_height = p_vpar->sequence.i_mb_height; - p_undec_p->i_mb_width = p_vpar->sequence.i_mb_width; - p_undec_p->i_pts = i_pts; + /* OK, now we are sure we will decode the picture. */ +#define P_picture p_vpar->picture.p_picture + p_vpar->picture.b_error = FALSE; + + if( !p_vpar->picture.i_current_structure ) + { + /* This is a new frame. Get a structure from the video_output. */ + P_picture = vout_CreatePicture( p_vpar->p_vout, + SPLITTED_YUV_PICTURE, + p_vpar->sequence.i_width, + p_vpar->sequence.i_height, + p_vpar->sequence.i_chroma_format ); + + /* Initialize values. */ + P_picture->date = vpar_SynchroDecode( p_vpar, i_coding_type, + i_structure ); + bzero( p_vpar->picture.pp_mb, MAX_MB*sizeof( macroblock_t * ) ); + p_vpar->picture.i_lum_incr = - 8 + ( p_vpar->sequence.i_width + << ( i_structure != FRAME_STRUCTURE ) ); + p_vpar->picture.i_chroma_incr = -8 + ( p_vpar->sequence.i_width + << (( i_structure != FRAME_STRUCTURE ) + + ( 3 - p_vpar->sequence.i_chroma_format )) ); + + /* Update the reference pointers. */ + ReferenceUpdate( p_vpar, i_coding_type, p_undec_p ); + } + p_vpar->picture.i_current_structure |= i_structure; + p_vpar->picture.i_structure = i_structure; + p_vpar->picture.b_frame_structure = (i_structure == FRAME_STRUCTURE); + + /* Initialize picture data for decoding. */ + if( i_structure == BOTTOM_FIELD ) + { + i_mb_base = p_vpar->sequence.i_mb_size >> 1; + } + else + { + i_mb_base = 0; + } + i_mb_address = 0; + + /* Extension and User data. */ + ExtensionAndUserData( p_vpar ); + + /* Picture data (ISO/IEC 13818-2 6.2.3.7). */ + NextStartCode( p_vpar ); + while( i_mb_address+i_mb_base < p_vpar->sequence.i_mb_size + && !p_vpar->picture.b_error) + { + if( ((i_dummy = ShowBits( &p_vpar->bit_stream, 32 )) + < SLICE_START_CODE_MIN) || + (i_dummy > SLICE_START_CODE_MAX) ) + { + intf_DbgMsg("vpar debug: premature end of picture"); + p_vpar->picture.b_error = TRUE; + break; + } + DumpBits32( &p_vpar->bit_stream ); + + /* Decode slice data. */ + SliceHeader( p_vpar, &i_mb_address, i_mb_base, i_dummy & 255 ); + } + + if( p_vpar->picture.b_error ) + { + /* Trash picture. */ + for( i_mb = 0; p_vpar->picture.pp_mb[i_mb]; i_mb++ ) + { + vpar_DestroyMacroblock( &p_vpar->vfifo, p_vpar->picture.pp_mb[i_mb] ); + } + + ReferenceReplace( p_vpar, p_vpar->picture.i_coding_type, NULL ); + vout_DestroyPicture( p_vpar->p_vout, P_picture ); + + /* Prepare context for the next picture. */ + P_picture = NULL: + } + else if( p_vpar->picture.i_current_structure == FRAME_STRUCTURE ) + { + /* Frame completely parsed. */ + for( i_mb = 0; i_mb < p_vpar->sequence.i_mb_size; i_mb++ ) + { + vpar_DecodeMacroblock( &p_vpar->vfifo, p_vpar->picture.pp_mb[i_mb] ); + } + + /* Prepare context for the next picture. */ + P_picture = NULL; + } +#undef P_picture } /***************************************************************************** @@ -455,11 +544,115 @@ static void __inline__ ReferenceUpdate( vpar_thread_t * p_vpar, { if( i_coding_type != B_CODING_TYPE ) { - /* The P picture would have become the new p_backward reference. */ - vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward ); + if( p_vpar->sequence.p_forward != NULL ) + vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward ); p_vpar->sequence.p_forward = p_vpar->sequence.p_backward; p_vpar->sequence.p_backward = p_newref; + if( p_newref != NULL ) + vout_LinkPicture( p_vpar->p_vout, p_newref ); + } +} + +/***************************************************************************** + * 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 ) +{ + if( i_coding_type != B_CODING_TYPE ) + { + if( p_vpar->sequence.p_backward != NULL ) + vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_backward ); + p_vpar->sequence.p_backward = p_newref; + if( p_newref != NULL ) + vout_LinkPicture( p_vpar->p_vout, p_newref ); + } +} + +/***************************************************************************** + * SliceHeaderXY : Parse the next slice structure + ***************************************************************************** + * X = i_height > 2800 ? + * Y = scalable_mode == SC_DP ? + *****************************************************************************/ +static void SliceHeader00( vpar_thread_t * p_vpar, + int * pi_mb_address, int i_mb_base, + u32 i_vert_code ) +{ + SliceHeader( p_vpar, pi_mb_address, i_mb_base, i_vert_code ); +} + +static void SliceHeader01( vpar_thread_t * p_vpar, + int * pi_mb_address, int i_mb_base, + u32 i_vert_code ) +{ + DumpBits( &p_vpar->bit_stream, 7 ); /* priority_breakpoint */ + SliceHeader( p_vpar, pi_mb_address, i_mb_base, i_vert_code ); +} + +static void SliceHeader10( vpar_thread_t * p_vpar, + int * pi_mb_address, int i_mb_base, + u32 i_vert_code ) +{ + i_vert_code += GetBits( &p_vpar->bit_stream, 3 ) << 7; + SliceHeader( p_vpar, pi_mb_address, i_mb_base, i_vert_code ); +} + +static void SliceHeader11( vpar_thread_t * p_vpar, + int * pi_mb_address, int i_mb_base, + u32 i_vert_code ) +{ + i_vert_code += GetBits( &p_vpar->bit_stream, 3 ) << 7; + DumpBits( &p_vpar->bit_stream, 7 ); /* priority_breakpoint */ + SliceHeader( p_vpar, pi_mb_address, i_mb_base, i_vert_code ); +} + +/***************************************************************************** + * SliceHeader : Parse the next slice structure + *****************************************************************************/ +static __inline__ void SliceHeader( vpar_thread_t * p_vpar, + int * pi_mb_address, int i_mb_base, + u32 i_vert_code ) +{ + /* DC predictors initialization table */ + static int pi_dc_dct_reinit[4] = {128,256,512,1024}; + + int i_mb_address_save = *pi_mb_address; + + /* slice_vertical_position_extension and priority_breakpoint already done */ + LoadQuantizerScale( p_vpar ); + + if( GetBits( &p_vpar->bit_stream, 1 ) ) + { + /* intra_slice, slice_id */ + DumpBits( &p_vpar->bit_stream, 8 ); + /* extra_information_slice */ + while( GetBits( &p_vpar->bit_stream, 1 ) ) + { + DumpBits( &p_vpar->bit_stream, 8 ); + } + } + + *pi_mb_address = (i_vert_code - 1)*p_vpar->sequence.i_mb_width; + + /* Reset DC coefficients predictors (ISO/IEC 13818-2 7.2.1). Why + * does the reference decoder put 0 instead of the normative values ? */ + p_vpar->slice.pi_dct_pred[0] = p_vpar->slice.pi_dct_pred[1] + = p_vpar->slice.pi_dct_pred[2] + = pi_dc_dct_reinit[p_vpar->picture.i_intra_dc_precision]; + + /* Reset motion vector predictors (ISO/IEC 13818-2 7.6.3.4). */ + bzero( p_vpar->slice.pppi_pmv, 8*sizeof(int) ); + + do + { + vpar_ParseMacroblock( p_vpar, pi_mb_address, i_mb_address_save, + i_mb_base ); + i_mb_address_save = *pi_mb_address; } + while( !ShowBits( &p_vpar->bit_stream, 23 ) ); } /***************************************************************************** @@ -563,4 +756,3 @@ static void LinkMatrix( quant_matrix_t * p_matrix, int * pi_array ) p_matrix->pi_matrix = pi_array; } - diff --git a/src/video_parser/vpar_motion.c b/src/video_parser/vpar_motion.c new file mode 100644 index 0000000000..7f9443dcda --- /dev/null +++ b/src/video_parser/vpar_motion.c @@ -0,0 +1,54 @@ +/***************************************************************************** + * vpar_motion.c : motion vectors parsing + * (c)1999 VideoLAN + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "common.h" +#include "mtime.h" +#include "vlc_thread.h" + +#include "intf_msg.h" +#include "debug.h" /* ?? temporaire, requis par netlist.h */ + +#include "input.h" +#include "input_netlist.h" +#include "decoder_fifo.h" +#include "video.h" +#include "video_output.h" +#include "video_parser.h" + +#include "video_fifo.h" +#include "video_decoder.h" + +/* + * Local prototypes + */ + +/***************************************************************************** + * vpar_MPEG1MotionVector : Parse the next MPEG-1 motion vector + *****************************************************************************/ +void vpar_MPEG1MotionVector( vpar_thread_t * p_vpar, int i_mv ) +{ + +} + +/***************************************************************************** + * vpar_MPEG2MotionVector : Parse the next MPEG-2 motion vector + *****************************************************************************/ +void vpar_MPEG2MotionVector( vpar_thread_t * p_vpar, int i_mv ) +{ + +} -- 2.39.2