Ticket #418: dirac.c

File dirac.c, 4.4 kB (added by Matthias, 3 months ago)
Line 
1 /*
2   dirac.c
3 */
4 //#include <stdint.h>
5
6 #include "dirac.h"
7
8 typedef unsigned char uint8_t;
9
10 typedef struct
11 dirac_bs_s
12 {
13   uint8_t *p_start;
14   uint8_t *p;
15   uint8_t *p_end;
16
17   int     i_left;    /* i_count number of available bits */
18 } dirac_bs_t;
19
20 static void
21 dirac_bs_init( dirac_bs_t *s, void *p_data, int i_data )
22 {
23   s->p_start = p_data;
24   s->p       = p_data;
25   s->p_end   = s->p + i_data;
26   s->i_left  = 8;
27 }
28
29 static ogg_uint32_t
30 dirac_bs_read( dirac_bs_t *s, int i_count )
31 {
32    static ogg_uint32_t i_mask[33] =
33    {  0x00,
34       0x01,      0x03,      0x07,      0x0f,
35       0x1f,      0x3f,      0x7f,      0xff,
36       0x1ff,     0x3ff,     0x7ff,     0xfff,
37       0x1fff,    0x3fff,    0x7fff,    0xffff,
38       0x1ffff,   0x3ffff,   0x7ffff,   0xfffff,
39       0x1fffff,  0x3fffff,  0x7fffff,  0xffffff,
40       0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
41       0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
42   int      i_shr;
43   ogg_uint32_t i_result = 0;
44
45   while( i_count > 0 )
46   {
47     if( s->p >= s->p_end )
48     {
49       break;
50     }
51
52     if( ( i_shr = s->i_left - i_count ) >= 0 )
53     {
54       /* more in the buffer than requested */
55       i_result |= ( *s->p >> i_shr )&i_mask[i_count];
56       s->i_left -= i_count;
57       if( s->i_left == 0 )
58       {
59         s->p++;
60         s->i_left = 8;
61       }
62       return( i_result );
63     }
64     else
65     {
66         /* less in the buffer than requested */
67        i_result |= (*s->p&i_mask[s->i_left]) << -i_shr;
68        i_count  -= s->i_left;
69        s->p++;
70        s->i_left = 8;
71     }
72   }
73
74   return( i_result );
75 }
76
77 static void
78 dirac_bs_skip( dirac_bs_t *s, int i_count )
79 {
80   s->i_left -= i_count;
81
82   while( s->i_left <= 0 )
83   {
84     s->p++;
85     s->i_left += 8;
86   }
87 }
88
89 static ogg_uint32_t
90 dirac_uint ( dirac_bs_t *p_bs )
91 {
92   ogg_uint32_t count = 0, value = 0;
93   while( !dirac_bs_read ( p_bs, 1 ) ) {
94     count++;
95     value <<= 1;
96     value |= dirac_bs_read ( p_bs, 1 );
97   }
98
99   return (1<<count) - 1 + value;
100 }
101
102 static int
103 dirac_bool ( dirac_bs_t *p_bs )
104 {
105   return dirac_bs_read ( p_bs, 1 );
106 }
107
108 void
109 dirac_parse_info (dirac_info *info, unsigned char * data, long len)
110 {
111   char * buf;
112   dirac_bs_t bs;
113   ogg_uint32_t video_format;
114
115   static const struct {
116     ogg_uint32_t fps_numerator, fps_denominator;
117   } dirac_frate_tbl[] = { /* table 10.3 */
118     {1,1}, /* this first value is never used */
119     {24000,1001}, {24,1}, {25,1}, {30000,1001}, {30,1},
120     {50,1}, {60000,1001}, {60,1}, {15000,1001}, {25,2},
121   };
122
123   static const ogg_uint32_t dirac_vidfmt_frate[] = { /* table C.1 */
124     1, 9, 10, 9, 10, 9, 10, 4, 3, 7, 6, 4, 3, 7, 6, 2, 2, 7, 6, 7, 6,
125   };
126
127   static const struct {
128     ogg_uint32_t width, height;
129   } dirac_fsize_tbl[] = { /* table 10.3 framesize */
130     {640,460}, {24,1}, {176,120}, {352,240}, {352,288},
131     {704,480}, {704,576}, {720,480}, {720,576},
132     {1280, 720}, {1280, 720}, {1920, 1080}, {1920, 1080},
133     {1920, 1080}, {1920, 1080}, {2048, 1080}, {4096, 2160}
134   };
135
136   /* read in useful bits from sequence header */
137   dirac_bs_init( &bs, data, len);
138   dirac_bs_skip( &bs, 13*8); /* parse_info_header */
139   info->major_version = dirac_uint( &bs ); /* major_version */
140   info->minor_version = dirac_uint( &bs ); /* minor_version */
141   info->profile = dirac_uint( &bs ); /* profile */
142   info->level = dirac_uint( &bs ); /* level */
143   info->video_format = video_format = dirac_uint( &bs ); /* index */
144
145   info->width = dirac_fsize_tbl[video_format].width;
146   info->height = dirac_fsize_tbl[video_format].height;
147   if (dirac_bool( &bs )) {
148     info->width = dirac_uint( &bs ); /* frame_width */
149     info->height = dirac_uint( &bs ); /* frame_height */
150   }
151
152   if (dirac_bool( &bs )) {
153     info->chroma_format = dirac_uint( &bs ); /* chroma_format */
154   }
155   if (dirac_bool( &bs )) {
156     info->interlaced = 0;
157     if (dirac_bool( &bs )) { /* interlaced */
158         info->interlaced = 1;
159         info->top_field_first = dirac_bool( &bs ); /* top_field_first */
160     }
161   }
162
163   info->fps_numerator = dirac_frate_tbl[dirac_vidfmt_frate[video_format]].fps_numerator;
164   info->fps_denominator = dirac_frate_tbl[dirac_vidfmt_frate[video_format]].fps_denominator;
165   if (dirac_bool( &bs )) {
166     ogg_uint32_t frame_rate_index = dirac_uint( &bs );
167     info->fps_numerator = dirac_frate_tbl[frame_rate_index].fps_numerator;
168     info->fps_denominator = dirac_frate_tbl[frame_rate_index].fps_denominator;
169     if (frame_rate_index == 0) {
170       info->fps_numerator = dirac_uint( &bs );
171       info->fps_denominator = dirac_uint( &bs );
172     }
173   }
174 }
175