2 * http://keyj.s2000.at/files/projects/h264-src.tar.gz
8 #define NAL_BUF_SIZE 65536 // maximum NAL unit size
9 #define RING_BUF_SIZE 8192 // input ring buffer size, MUST be a power of two!
11 typedef struct _nal_unit {
12 int NumBytesInNALunit;
13 int forbidden_zero_bit;
16 unsigned char *last_rbsp_byte;
19 typedef struct _slice_header {
20 int first_mb_in_slice;
23 static int get_next_nal_unit(FILE *input_fp, nal_unit *nalu);
24 static int get_unsigned_exp_golomb();
25 static void decode_slice_header(slice_header *sh);
26 static void input_read(FILE *input_fp, unsigned char *dest, int size);
27 static int input_get_bits(int bit_count);
30 static unsigned char nal_buf[NAL_BUF_SIZE];
31 static unsigned char ring_buf[RING_BUF_SIZE];
32 static int input_remain = 0;
33 static int ring_pos = 0;
36 static int frame_no = 0;
38 #define RING_MOD ((RING_BUF_SIZE)-1)
39 #define HALF_RING ((RING_BUF_SIZE)/2)
41 #define gnn_advance() do { \
42 ring_pos = (ring_pos+1)&RING_MOD; \
44 if (ring_pos==0) input_read(input_fp, &ring_buf[HALF_RING],HALF_RING); \
45 if (ring_pos==HALF_RING) input_read(input_fp, &ring_buf[0],HALF_RING); \
48 #define gnn_add_segment(end) do { \
49 int size = end-segment_start; \
51 memcpy(&nal_buf[nalu_size],&ring_buf[segment_start],size); \
54 segment_start = end&RING_MOD; \
57 static int input_get_bits(int bit_count)
60 register unsigned int x =
61 (nal_buf[nal_pos]<<24)|
62 (nal_buf[nal_pos+1]<<16)|
63 (nal_buf[nal_pos+2]<<8)|
66 res = (x>>(32-bit_count-nal_bit))&((1<<bit_count)-1);
68 nal_pos += nal_bit>>3;
74 static int input_get_one_bit()
76 int res = (nal_buf[nal_pos]>>(7-nal_bit))&1;
85 static int get_unsigned_exp_golomb()
89 for(exp = 0; !input_get_one_bit(); ++exp);
92 return (1<<exp) - 1 + input_get_bits(exp);
97 static void decode_slice_header(slice_header *sh )
99 memset((void*)sh,0,sizeof(slice_header));
100 sh->first_mb_in_slice = get_unsigned_exp_golomb();
103 static void input_read(FILE *input_fp, unsigned char *dest, int size)
105 int count = fread(dest, 1, size, input_fp);
107 input_remain += count;
110 static int get_next_nal_unit(FILE *input_fp, nal_unit *nalu)
114 int NumBytesInRbsp = 0;
116 /* search for the next NALU start
117 * here is the sync that the start of the NALU is 0x00000001
120 if (input_remain<= 4) {
122 memset(ring_buf,0,sizeof(char)*RING_BUF_SIZE);
123 memset(nal_buf,0,sizeof(char)*NAL_BUF_SIZE);
125 fseek(input_fp,0,SEEK_SET);
127 input_read(input_fp, ring_buf, RING_BUF_SIZE);
131 if ((!ring_buf[ring_pos]) &&
132 (!ring_buf[(ring_pos+1)&RING_MOD]) &&
133 (!ring_buf[(ring_pos+2)&RING_MOD]) &&
134 ( ring_buf[(ring_pos+3)&RING_MOD]==1))
142 /* add bytes to the NALU until the end is found */
143 segment_start = ring_pos;
144 while (input_remain) {
145 if ((!ring_buf[ring_pos]) &&
146 (!ring_buf[(ring_pos+1)&RING_MOD]) &&
147 (!ring_buf[(ring_pos+2)&RING_MOD]))
149 ring_pos = (ring_pos+1)&RING_MOD;
153 gnn_add_segment(RING_BUF_SIZE);
154 input_read(input_fp, &ring_buf[HALF_RING],HALF_RING);
157 if (ring_pos==HALF_RING) {
158 gnn_add_segment(HALF_RING);
159 input_read(input_fp, &ring_buf[0], HALF_RING);
163 gnn_add_segment(ring_pos);
165 /* read the NAL unit */
166 nal_pos = 0; nal_bit = 0;
167 nalu->forbidden_zero_bit = input_get_bits(1);
168 nalu->nal_ref_idc = input_get_bits(2);
169 nalu->nal_unit_type = input_get_bits(5);
170 nalu->last_rbsp_byte = &nal_buf[nalu_size-1];
171 nalu->NumBytesInNALunit = nalu_size;
176 int va_FoolGetFrame(FILE *input_fp, char *frame_buf)
178 int i = 0, frame_pos = 0;
179 static slice_header sh;
180 static nal_unit nalu;
181 char nal_head[4] = {0x00,0x00,0x00,0x01};
183 /* read the clip , here is the first frame,
184 * &let the clip go on frame by frame
187 input_read(input_fp, ring_buf,RING_BUF_SIZE);
189 while (get_next_nal_unit(input_fp, &nalu)) {
190 if (nalu.nal_unit_type == 7 || nalu.nal_unit_type == 8) {
191 memcpy(frame_buf+frame_pos, nal_head, sizeof(char)*4);
192 frame_pos = frame_pos + 4;
193 memcpy(frame_buf+frame_pos, nal_buf, sizeof(char)*(nalu.NumBytesInNALunit));
194 frame_pos += nalu.NumBytesInNALunit;
196 else if (nalu.nal_unit_type == 1 || nalu.nal_unit_type == 5) {
197 decode_slice_header(&sh);
198 if (0 == sh.first_mb_in_slice) {
201 memcpy(frame_buf+frame_pos, nal_head, sizeof(char)*4);
202 frame_pos = frame_pos + 4;
203 memcpy(frame_buf+frame_pos, nal_buf, sizeof(char)*(nalu.NumBytesInNALunit));
204 frame_pos += nalu.NumBytesInNALunit;