+
+/* every packet[1] in the stream contains a picture, there may
+ * be header cruft infront of it though
+ * [1] EXCEPT the BOS page/packet */
+static uint32_t Ogg_ReadDiracPictureNumber( ogg_packet *p_oggpacket )
+{
+ uint32_t u_pos = 4;
+ /* find the picture startcode */
+ while ( (p_oggpacket->packet[u_pos] & 0x08) == 0) {
+ /* skip to the next dirac parse unit */
+ u_pos += GetDWBE( p_oggpacket->packet + u_pos + 1 );
+ /* protect against falling off the edge */
+ if ( u_pos > p_oggpacket->bytes )
+ return -1;
+ }
+
+ uint32_t u_pnum = GetDWBE( p_oggpacket->packet + u_pos + 9 );
+
+ return u_pnum;
+}
+
+static uint32_t dirac_uint( bs_t *p_bs )
+{
+ uint32_t count = 0, value = 0;
+ while( !bs_read ( p_bs, 1 ) ) {
+ count++;
+ value <<= 1;
+ value |= bs_read ( p_bs, 1 );
+ }
+
+ return (1<<count) - 1 + value;
+}
+
+static int dirac_bool( bs_t *p_bs )
+{
+ return bs_read ( p_bs, 1 );
+}
+
+static void Ogg_ReadDiracHeader( logical_stream_t *p_stream,
+ ogg_packet *p_oggpacket )
+{
+ bs_t bs;
+
+ p_stream->fmt.i_cat = VIDEO_ES;
+ p_stream->fmt.i_codec = VLC_FOURCC( 'd','r','a','c' );
+ p_stream->i_granule_shift = 32;
+
+ /* Backing up stream headers is not required -- seqhdrs are repeated
+ * thoughout the stream at suitable decoding start points */
+ p_stream->b_force_backup = 0;
+
+ /* read in useful bits from sequence header */
+ bs_init( &bs, p_oggpacket->packet, p_oggpacket->bytes );
+ bs_skip( &bs, 13*8); /* parse_info_header */
+ dirac_uint( &bs ); /* major_version */
+ dirac_uint( &bs ); /* minor_version */
+ dirac_uint( &bs ); /* profile */
+ dirac_uint( &bs ); /* level */
+
+ uint32_t u_video_format = dirac_uint( &bs ); /* index */
+
+ if (dirac_bool( &bs )) {
+ dirac_uint( &bs ); /* frame_width */
+ dirac_uint( &bs ); /* frame_height */
+ }
+
+ if (dirac_bool( &bs )) {
+ dirac_uint( &bs ); /* chroma_format */
+ }
+ if (dirac_bool( &bs )) {
+ if (dirac_bool( &bs )) { /* interlaced */
+ dirac_bool( &bs ); /* top_field_first */
+ }
+ }
+
+ static const struct {
+ uint32_t u_n /* numerator */, u_d /* denominator */;
+ } dirac_frate_tbl[] = { /* table 10.3 */
+ {24000,1001}, {24,1}, {25,1}, {30000,1001}, {30,1},
+ {50,1}, {60000,1001}, {60,1}, {15000,1001}, {25,2},
+ };
+
+ static const uint32_t dirac_vidfmt_frate[] = { /* table C.1 */
+ 1, 9, 10, 9, 10, 9, 10, 4, 3, 7, 6, 4, 3, 7, 6, 2, 2, 7, 6, 7, 6,
+ };
+
+ uint32_t u_n = dirac_frate_tbl[dirac_vidfmt_frate[u_video_format]].u_n;
+ uint32_t u_d = dirac_frate_tbl[dirac_vidfmt_frate[u_video_format]].u_d;
+ if (dirac_bool( &bs )) {
+ uint32_t frame_rate_index = dirac_uint( &bs );
+ u_n = dirac_frate_tbl[frame_rate_index].u_n;
+ u_d = dirac_frate_tbl[frame_rate_index].u_d;
+ if (frame_rate_index == 0) {
+ u_n = dirac_uint( &bs ); /* frame_rate_numerator */
+ u_d = dirac_uint( &bs ); /* frame_rate_denominator */
+ }
+ }
+ p_stream->f_rate = (float) u_n / u_d;
+}