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