]> git.sesse.net Git - vlc/blob - modules/packetizer/vc1.c
Fixed extra data parsing with some VC1 streams.
[vlc] / modules / packetizer / vc1.c
1 /*****************************************************************************
2  * vc1.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002, 2006 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Gildas Bazin <gbazin@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_codec.h>
36 #include <vlc_block.h>
37
38 #include "vlc_bits.h"
39 #include "vlc_block_helper.h"
40
41 /*****************************************************************************
42  * Module descriptor
43  *****************************************************************************/
44 static int  Open ( vlc_object_t * );
45 static void Close( vlc_object_t * );
46
47 vlc_module_begin ()
48     set_category( CAT_SOUT )
49     set_subcategory( SUBCAT_SOUT_PACKETIZER )
50     set_description( N_("VC-1 packetizer") )
51     set_capability( "packetizer", 50 )
52     set_callbacks( Open, Close )
53 vlc_module_end ()
54
55 /*****************************************************************************
56  * Local prototypes
57  *****************************************************************************/
58 struct decoder_sys_t
59 {
60     /*
61      * Input properties
62      */
63     block_bytestream_t bytestream;
64     int i_state;
65     size_t i_offset;
66     uint8_t p_startcode[3];
67
68     /* Current sequence header */
69     bool b_sequence_header;
70     struct
71     {
72         block_t *p_sh;
73         bool b_advanced_profile;
74         bool b_interlaced;
75         bool b_frame_interpolation;
76         bool b_range_reduction;
77         bool b_has_bframe;
78     } sh;
79     bool b_entry_point;
80     struct
81     {
82         block_t *p_ep;
83     } ep;
84
85     /* */
86     bool  b_frame;
87
88     /* Current frame being built */
89     block_t    *p_frame;
90     block_t    **pp_last;
91
92
93     mtime_t i_interpolated_dts;
94 };
95
96 enum
97 {
98     STATE_NOSYNC,
99     STATE_NEXT_SYNC
100 };
101
102 typedef enum
103 {
104     IDU_TYPE_SEQUENCE_HEADER = 0x0f,
105     IDU_TYPE_ENTRY_POINT = 0x0e,
106     IDU_TYPE_FRAME = 0x0D,
107     IDU_TYPE_FIELD = 0x0C,
108     IDU_TYPE_SLICE = 0x0B,
109     IDU_TYPE_END_OF_SEQUENCE = 0x0A,
110
111     IDU_TYPE_SEQUENCE_LEVEL_USER_DATA = 0x1F,
112     IDU_TYPE_ENTRY_POINT_USER_DATA = 0x1E,
113     IDU_TYPE_FRAME_USER_DATA = 0x1D,
114     IDU_TYPE_FIELD_USER_DATA = 0x1C,
115     IDU_TYPE_SLICE_USER_DATA = 0x1B,
116 } idu_type_t;
117
118 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block );
119
120 /*****************************************************************************
121  * Open: probe the packetizer and return score
122  *****************************************************************************
123  * Tries to launch a decoder and return score so that the interface is able
124  * to choose.
125  *****************************************************************************/
126 static int Open( vlc_object_t *p_this )
127 {
128     decoder_t     *p_dec = (decoder_t*)p_this;
129     decoder_sys_t *p_sys;
130
131     if( p_dec->fmt_in.i_codec !=  VLC_FOURCC( 'W', 'V', 'C', '1' ) )
132         return VLC_EGENERIC;
133
134     p_dec->pf_packetize = Packetize;
135
136     /* Create the output format */
137     es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
138     p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
139
140     p_sys->i_state = STATE_NOSYNC;
141     p_sys->bytestream = block_BytestreamInit();
142     p_sys->p_startcode[0] = 0x00;
143     p_sys->p_startcode[1] = 0x00;
144     p_sys->p_startcode[2] = 0x01;
145     p_sys->i_offset = 0;
146
147     p_sys->b_sequence_header = false;
148     p_sys->sh.p_sh = NULL;
149     p_sys->b_entry_point = false;
150     p_sys->ep.p_ep = NULL;
151
152     p_sys->b_frame = false;
153     p_sys->p_frame = NULL;
154     p_sys->pp_last = &p_sys->p_frame;
155
156     p_sys->i_interpolated_dts = -1;
157
158     /* */
159     if( p_dec->fmt_out.i_extra > 0 )
160     {
161         uint8_t *p_extra = p_dec->fmt_out.p_extra;
162
163         /* With (some) ASF the first byte has to be stripped */
164         if( p_extra[0] != 0x00 )
165         {
166             memcpy( &p_extra[0], &p_extra[1], p_dec->fmt_out.i_extra - 1 );
167             p_dec->fmt_out.i_extra--;
168         }
169
170         /* */
171         if( p_dec->fmt_out.i_extra > 0 )
172         {
173             block_t *p_init = block_New( p_dec, p_dec->fmt_out.i_extra );
174
175             memcpy( p_init->p_buffer, p_dec->fmt_out.p_extra,
176                     p_dec->fmt_out.i_extra );
177
178             block_t *p_pic;
179             while( ( p_pic = Packetize( p_dec, &p_init ) ) )
180                 block_Release( p_pic ); /* Should not happen (only sequence header) */
181         }
182     }
183
184     return VLC_SUCCESS;
185 }
186
187 /*****************************************************************************
188  * Close:
189  *****************************************************************************/
190 static void Close( vlc_object_t *p_this )
191 {
192     decoder_t     *p_dec = (decoder_t*)p_this;
193     decoder_sys_t *p_sys = p_dec->p_sys;
194
195     block_BytestreamRelease( &p_sys->bytestream );
196     if( p_sys->p_frame )
197         block_Release( p_sys->p_frame );
198     free( p_sys );
199 }
200
201 /*****************************************************************************
202  * Packetize: packetize an access unit
203  *****************************************************************************/
204 static block_t *ParseIDU( decoder_t *p_dec, bool *pb_used_ts, block_t *p_frag );
205
206 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
207 {
208     decoder_sys_t *p_sys = p_dec->p_sys;
209     block_t       *p_pic;
210
211     if( pp_block == NULL || *pp_block == NULL )
212         return NULL;
213
214     if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
215     {
216         if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
217         {
218             p_sys->i_state = STATE_NOSYNC;
219             block_BytestreamEmpty( &p_sys->bytestream );
220
221             if( p_sys->p_frame )
222                 block_ChainRelease( p_sys->p_frame );
223             p_sys->p_frame = NULL;
224             p_sys->pp_last = &p_sys->p_frame;
225             p_sys->b_frame = false;
226         }
227         p_sys->i_interpolated_dts = 0;
228         block_Release( *pp_block );
229         return NULL;
230     }
231
232     block_BytestreamPush( &p_sys->bytestream, *pp_block );
233
234     for( ;; )
235     {
236         bool b_used_ts;
237
238         switch( p_sys->i_state )
239         {
240
241         case STATE_NOSYNC:
242             if( block_FindStartcodeFromOffset( &p_sys->bytestream, &p_sys->i_offset, p_sys->p_startcode, 3 ) == VLC_SUCCESS )
243                 p_sys->i_state = STATE_NEXT_SYNC;
244
245             if( p_sys->i_offset )
246             {
247                 block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
248                 p_sys->i_offset = 0;
249                 block_BytestreamFlush( &p_sys->bytestream );
250             }
251
252             if( p_sys->i_state != STATE_NEXT_SYNC )
253                 return NULL; /* Need more data */
254
255             p_sys->i_offset = 4; /* To find next startcode */
256
257         case STATE_NEXT_SYNC:
258             /* TODO: If p_block == NULL, flush the buffer without checking the
259              * next sync word */
260
261             /* Find the next startcode */
262             if( block_FindStartcodeFromOffset( &p_sys->bytestream, &p_sys->i_offset, p_sys->p_startcode, 3 ) != VLC_SUCCESS )
263                 return NULL; /* Need more data */
264
265             /* Get the new fragment and set the pts/dts */
266             p_pic = block_New( p_dec, p_sys->i_offset );
267             block_BytestreamFlush( &p_sys->bytestream );
268             p_pic->i_pts = p_sys->bytestream.p_block->i_pts;
269             p_pic->i_dts = p_sys->bytestream.p_block->i_dts;
270
271             block_GetBytes( &p_sys->bytestream, p_pic->p_buffer, p_pic->i_buffer );
272
273             p_sys->i_offset = 0;
274
275             /* Parse and return complete frame */
276             p_pic = ParseIDU( p_dec, &b_used_ts, p_pic );
277
278             /* Don't reuse the same timestamps several times */
279             if( b_used_ts )
280             {
281                 p_sys->bytestream.p_block->i_pts = -1;
282                 p_sys->bytestream.p_block->i_dts = -1;
283             }
284
285             /* */
286             if( !p_pic )
287             {
288                 p_sys->i_state = STATE_NOSYNC;
289                 break;
290             }
291             /* */
292             if( p_sys->i_interpolated_dts < 0 )
293             {
294                 msg_Dbg( p_dec, "need a starting pts/dts" );
295                 p_sys->i_state = STATE_NOSYNC;
296                 block_Release( p_pic );
297                 break;
298             }
299
300             /* So p_block doesn't get re-added several times */
301             *pp_block = block_BytestreamPop( &p_sys->bytestream );
302
303             p_sys->i_state = STATE_NOSYNC;
304
305             return p_pic;
306         }
307     }
308 }
309
310 /* DecodeRIDU: decode the startcode emulation prevention (same than h264) */
311 static void DecodeRIDU( uint8_t *p_ret, int *pi_ret, uint8_t *src, int i_src )
312 {
313     uint8_t *end = &src[i_src];
314     uint8_t *dst_end = &p_ret[*pi_ret];
315     uint8_t *dst = p_ret;
316
317     while( src < end && dst < dst_end )
318     {
319         if( src < end - 3 && src[0] == 0x00 && src[1] == 0x00 &&
320             src[2] == 0x03 )
321         {
322             *dst++ = 0x00;
323             *dst++ = 0x00;
324
325             src += 3;
326             continue;
327         }
328         *dst++ = *src++;
329     }
330
331     *pi_ret = dst - p_ret;
332 }
333 /* BuildExtraData: gather sequence header and entry point */
334 static void BuildExtraData( decoder_t *p_dec )
335 {
336     decoder_sys_t *p_sys = p_dec->p_sys;
337     es_format_t *p_es = &p_dec->fmt_out;
338     int i_extra;
339     if( !p_sys->b_sequence_header || !p_sys->b_entry_point )
340         return;
341
342     i_extra = p_sys->sh.p_sh->i_buffer + p_sys->ep.p_ep->i_buffer;
343     if( p_es->i_extra != i_extra )
344     {
345         p_es->i_extra = i_extra;
346         p_es->p_extra = realloc( p_dec->fmt_out.p_extra, p_es->i_extra );
347     }
348     memcpy( p_es->p_extra,
349             p_sys->sh.p_sh->p_buffer, p_sys->sh.p_sh->i_buffer );
350     memcpy( (uint8_t*)p_es->p_extra + p_sys->sh.p_sh->i_buffer,
351             p_sys->ep.p_ep->p_buffer, p_sys->ep.p_ep->i_buffer );
352 }
353 /* ParseIDU: parse an Independent Decoding Unit */
354 static block_t *ParseIDU( decoder_t *p_dec, bool *pb_used_ts, block_t *p_frag )
355 {
356     decoder_sys_t *p_sys = p_dec->p_sys;
357     block_t *p_pic;
358     const idu_type_t idu = p_frag->p_buffer[3];
359
360     *pb_used_ts = false;
361     if( !p_sys->b_sequence_header && idu != IDU_TYPE_SEQUENCE_HEADER )
362     {
363         msg_Warn( p_dec, "waiting for sequence header" );
364         block_Release( p_frag );
365         return NULL;
366     }
367     if( p_sys->b_sequence_header && !p_sys->b_entry_point && idu != IDU_TYPE_ENTRY_POINT )
368     {
369         msg_Warn( p_dec, "waiting for entry point" );
370         block_Release( p_frag );
371         return NULL;
372     }
373     /* TODO we do not gather ENTRY_POINT and SEQUENCE_DATA user data
374      * But It should not be a problem for decoder */
375
376     /* Do we have completed a frame */
377     p_pic = NULL;
378     if( p_sys->b_frame &&
379         idu != IDU_TYPE_FRAME_USER_DATA &&
380         idu != IDU_TYPE_FIELD && idu != IDU_TYPE_FIELD_USER_DATA &&
381         idu != IDU_TYPE_SLICE && idu != IDU_TYPE_SLICE_USER_DATA &&
382         idu != IDU_TYPE_END_OF_SEQUENCE )
383     {
384         /* */
385         p_pic = block_ChainGather( p_sys->p_frame );
386
387         /* */
388         if( p_pic->i_dts > 0 )
389             p_sys->i_interpolated_dts = p_pic->i_dts;
390
391         /* We can interpolate dts/pts only if we have a frame rate */
392         if( p_dec->fmt_out.video.i_frame_rate != 0 && p_dec->fmt_out.video.i_frame_rate_base != 0 )
393         {
394             if( p_sys->i_interpolated_dts > 0 )
395                 p_sys->i_interpolated_dts += INT64_C(1000000) *
396                                              p_dec->fmt_out.video.i_frame_rate_base /
397                                              p_dec->fmt_out.video.i_frame_rate;
398
399             //msg_Dbg( p_dec, "-------------- XXX0 dts=%"PRId64" pts=%"PRId64" interpolated=%"PRId64,
400             //         p_pic->i_dts, p_pic->i_pts, p_sys->i_interpolated_dts );
401             if( p_pic->i_dts <= 0 )
402                 p_pic->i_dts = p_sys->i_interpolated_dts;
403
404             if( p_pic->i_pts <= 0 )
405             {
406                 if( !p_sys->sh.b_has_bframe || (p_pic->i_flags & BLOCK_FLAG_TYPE_B ) )
407                     p_pic->i_pts = p_pic->i_dts;
408                 /* TODO compute pts for other case */
409             }
410         }
411
412         //msg_Dbg( p_dec, "-------------- dts=%"PRId64" pts=%"PRId64, p_pic->i_dts, p_pic->i_pts );
413
414         /* Reset context */
415         p_sys->b_frame = false;
416         p_sys->p_frame = NULL;
417         p_sys->pp_last = &p_sys->p_frame;
418     }
419
420     /*  */
421     if( p_sys->p_frame )
422     {
423         block_t *p_frame = p_sys->p_frame;
424         if( p_frame->i_dts <= 0 && p_frame->i_pts <= 0 )
425         {
426             p_frame->i_dts = p_frag->i_dts;
427             p_frame->i_pts = p_frag->i_pts;
428             *pb_used_ts = true;
429         }
430     }
431     block_ChainLastAppend( &p_sys->pp_last, p_frag );
432
433     /* Parse IDU */
434     if( idu == IDU_TYPE_SEQUENCE_HEADER )
435     {
436         es_format_t *p_es = &p_dec->fmt_out;
437         bs_t s;
438         int i_profile;
439         uint8_t ridu[32];
440         int     i_ridu = sizeof(ridu);
441
442         /* */
443         if( p_sys->sh.p_sh )
444             block_Release( p_sys->sh.p_sh );
445         p_sys->sh.p_sh = block_Duplicate( p_frag );
446
447         /* Extract the raw IDU */
448         DecodeRIDU( ridu, &i_ridu, &p_frag->p_buffer[4], p_frag->i_buffer - 4 );
449
450         /* Auto detect VC-1_SPMP_PESpacket_PayloadFormatHeader (SMPTE RP 227) for simple/main profile
451          * TODO find a test case and valid it */
452         if( i_ridu > 4 && (ridu[0]&0x80) == 0 ) /* for advanced profile, the first bit is 1 */
453         {
454             video_format_t *p_v = &p_dec->fmt_in.video;
455             const size_t i_potential_width  = GetWBE( &ridu[0] );
456             const size_t i_potential_height = GetWBE( &ridu[2] );
457
458             if( i_potential_width >= 2  && i_potential_width <= 8192 &&
459                 i_potential_height >= 2 && i_potential_height <= 8192 )
460             {
461                 if( ( p_v->i_width <= 0 && p_v->i_height <= 0  ) ||
462                     ( p_v->i_width  == i_potential_width &&  p_v->i_height == i_potential_height ) )
463                 {
464                     static const uint8_t startcode[4] = { 0x00, 0x00, 0x01, IDU_TYPE_SEQUENCE_HEADER };
465                     p_es->video.i_width  = i_potential_width;
466                     p_es->video.i_height = i_potential_height;
467
468                     /* Remove it */
469                     p_frag->p_buffer += 4;
470                     p_frag->i_buffer -= 4;
471                     memcpy( p_frag->p_buffer, startcode, sizeof(startcode) );
472                 }
473             }
474         }
475
476         /* Parse it */
477         bs_init( &s, ridu, i_ridu );
478         i_profile = bs_read( &s, 2 );
479         if( i_profile == 3 )
480         {
481             const int i_level = bs_read( &s, 3 );
482
483             /* Advanced profile */
484             p_sys->sh.b_advanced_profile = true;
485             p_sys->sh.b_range_reduction = false;
486             p_sys->sh.b_has_bframe = true;
487
488             bs_skip( &s, 2+3+5+1 ); // chroma format + frame rate Q + bit rate Q + postprocflag
489
490             p_es->video.i_width  = 2*bs_read( &s, 12 )+2;
491             p_es->video.i_height = 2*bs_read( &s, 12 )+2;
492
493             if( !p_sys->b_sequence_header )
494                 msg_Dbg( p_dec, "found sequence header for advanced profile level L%d resolution %dx%d",
495                          i_level, p_es->video.i_width, p_es->video.i_height);
496
497             bs_skip( &s, 1 );// pulldown
498             p_sys->sh.b_interlaced = bs_read( &s, 1 );
499             bs_skip( &s, 1 );// frame counter
500             p_sys->sh.b_frame_interpolation = bs_read( &s, 1 );
501             bs_skip( &s, 1 );       // Reserved
502             bs_skip( &s, 1 );       // Psf
503
504             if( bs_read( &s, 1 ) )  /* Display extension */
505             {
506                 const int i_display_width  = bs_read( &s, 14 )+1;
507                 const int i_display_height = bs_read( &s, 14 )+1;
508
509                 p_es->video.i_aspect = VOUT_ASPECT_FACTOR * i_display_width / i_display_height;
510
511                 if( !p_sys->b_sequence_header )
512                     msg_Dbg( p_dec, "display size %dx%d", i_display_width, i_display_height );
513
514                 if( bs_read( &s, 1 ) )  /* Pixel aspect ratio (PAR/SAR) */
515                 {
516                     static const int p_ar[16][2] = {
517                         { 0, 0}, { 1, 1}, {12,11}, {10,11}, {16,11}, {40,33},
518                         {24,11}, {20,11}, {32,11}, {80,33}, {18,11}, {15,11},
519                         {64,33}, {160,99},{ 0, 0}, { 0, 0}
520                     };
521                     int i_ar = bs_read( &s, 4 );
522                     unsigned i_ar_w, i_ar_h;
523
524                     if( i_ar == 15 )
525                     {
526                         i_ar_w = bs_read( &s, 8 );
527                         i_ar_h = bs_read( &s, 8 );
528                     }
529                     else
530                     {
531                         i_ar_w = p_ar[i_ar][0];
532                         i_ar_h = p_ar[i_ar][1];
533                     }
534                     vlc_ureduce( &i_ar_w, &i_ar_h, i_ar_w, i_ar_h, 0 );
535                     if( !p_sys->b_sequence_header )
536                         msg_Dbg( p_dec, "aspect ratio %d:%d", i_ar_w, i_ar_h );
537                 }
538             }
539             if( bs_read( &s, 1 ) )  /* Frame rate */
540             {
541                 int i_fps_num = 0;
542                 int i_fps_den = 0;
543                 if( bs_read( &s, 1 ) )
544                 {
545                     i_fps_num = bs_read( &s, 16 )+1;
546                     i_fps_den = 32;
547                 }
548                 else
549                 {
550                     const int i_nr = bs_read( &s, 8 );
551                     const int i_dn = bs_read( &s, 4 );
552
553                     switch( i_nr )
554                     {
555                     case 1: i_fps_num = 24000; break;
556                     case 2: i_fps_num = 25000; break;
557                     case 3: i_fps_num = 30000; break;
558                     case 4: i_fps_num = 50000; break;
559                     case 5: i_fps_num = 60000; break;
560                     case 6: i_fps_num = 48000; break;
561                     case 7: i_fps_num = 72000; break;
562                     }
563                     switch( i_dn )
564                     {
565                     case 1: i_fps_den = 1000; break;
566                     case 2: i_fps_den = 1001; break;
567                     }
568                 }
569                 if( i_fps_num != 0 && i_fps_den != 0 )
570                     vlc_ureduce( &p_es->video.i_frame_rate, &p_es->video.i_frame_rate_base, i_fps_num, i_fps_den, 0 );
571
572                 if( !p_sys->b_sequence_header )
573                     msg_Dbg( p_dec, "frame rate %d/%d", p_es->video.i_frame_rate, p_es->video.i_frame_rate_base );
574             }
575         }
576         else
577         {
578             /* Simple and main profile */
579             p_sys->sh.b_advanced_profile = false;
580             p_sys->sh.b_interlaced = false;
581
582             if( !p_sys->b_sequence_header )
583                 msg_Dbg( p_dec, "found sequence header for %s profile", i_profile == 0 ? "simple" : "main" );
584
585             bs_skip( &s, 2+3+5+1+1+     // reserved + frame rate Q + bit rate Q + loop filter + reserved
586                          1+1+1+1+2+     // multiresolution + reserved + fast uv mc + extended mv + dquant
587                          1+1+1+1 );     // variable size transform + reserved + overlap + sync marker
588             p_sys->sh.b_range_reduction = bs_read( &s, 1 );
589             if( bs_read( &s, 3 ) > 0 )
590                 p_sys->sh.b_has_bframe = true;
591             else
592                 p_sys->sh.b_has_bframe = false;
593             bs_skip( &s, 2 );           // quantizer
594
595             p_sys->sh.b_frame_interpolation = bs_read( &s, 1 );
596         }
597         p_sys->b_sequence_header = true;
598         BuildExtraData( p_dec );
599     }
600     else if( idu == IDU_TYPE_ENTRY_POINT )
601     {
602         if( p_sys->ep.p_ep )
603             block_Release( p_sys->ep.p_ep );
604         p_sys->ep.p_ep = block_Duplicate( p_frag );
605
606         p_sys->b_entry_point = true;
607         BuildExtraData( p_dec );
608     }
609     else if( idu == IDU_TYPE_FRAME )
610     {
611         bs_t s;
612         uint8_t ridu[8];
613         int     i_ridu = sizeof(ridu);
614
615         /* Extract the raw IDU */
616         DecodeRIDU( ridu, &i_ridu, &p_frag->p_buffer[4], p_frag->i_buffer - 4 );
617
618         /* Parse it + interpolate pts/dts if possible */
619         bs_init( &s, ridu, i_ridu );
620
621         if( p_sys->sh.b_advanced_profile )
622         {
623             int i_fcm = 0;
624
625             if( p_sys->sh.b_interlaced )
626             {
627                 if( bs_read( &s, 1 ) )
628                 {
629                     if( bs_read( &s, 1 ) )
630                         i_fcm = 1;  /* interlaced field */
631                     else
632                         i_fcm = 2;  /* interlaced frame */
633                 }
634             }
635
636             if( i_fcm == 1 ) /*interlaced field */
637             {
638                 /* XXX for mixed I/P we should check reference usage before marking them I (too much work) */
639                 switch( bs_read( &s, 3 ) )
640                 {
641                 case 0: /* II */
642                 case 1: /* IP */
643                 case 2: /* PI */
644                     p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
645                     p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
646                     p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
647                     break;
648                 case 3: /* PP */
649                     p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P;
650                     break;
651                 case 4: /* BB */
652                 case 5: /* BBi */
653                 case 6: /* BiB */
654                 case 7: /* BiBi */
655                     p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B;
656                     break;
657                 }
658             }
659             else
660             {
661                 if( !bs_read( &s, 1 ) )
662                     p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P;
663                 else if( !bs_read( &s, 1 ) )
664                     p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B;
665                 else if( !bs_read( &s, 1 ) )
666                     p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
667                 else if( !bs_read( &s, 1 ) )
668                     p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B;   /* Bi */
669                 else
670                     p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P;   /* P Skip */
671             }
672         }
673         else
674         {
675             if( p_sys->sh.b_frame_interpolation )
676                 bs_skip( &s, 1 );   // interpolate
677             bs_skip( &s, 2 );       // frame count
678             if( p_sys->sh.b_range_reduction )
679                 bs_skip( &s, 1 );   // range reduction
680
681             if( bs_read( &s, 1 ) )
682                 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P;
683             else if( !p_sys->sh.b_has_bframe || bs_read( &s, 1 ) )
684                 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I;
685             else
686                 p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B;
687         }
688         p_sys->b_frame = true;
689     }
690     return p_pic;
691 }
692