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