Mercurial > libavcodec.hg
annotate h264_parser.c @ 9930:32e856bd5ded libavcodec
Check for CONFIG_LIBFOO_DECODER/CONFIG_LIBFOO_ENCODER instead of just
CONFIG_LIBFOO in the external libraries section.
This is more consistent with the rest of the Makefiles, it makes clearer what
is actually implemented and should be advantageous if we implement an external
library encoder where we previously just had the decoder and vice versa.
author | diego |
---|---|
date | Tue, 07 Jul 2009 09:33:08 +0000 |
parents | cb73e3273191 |
children | 916df4ea4e64 |
rev | line source |
---|---|
4975 | 1 /* |
2 * H.26L/H.264/AVC/JVT/14496-10/... parser | |
3 * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at> | |
4 * | |
5 * This file is part of FFmpeg. | |
6 * | |
7 * FFmpeg is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Lesser General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2.1 of the License, or (at your option) any later version. | |
11 * | |
12 * FFmpeg is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
18 * License along with FFmpeg; if not, write to the Free Software | |
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 */ | |
21 | |
22 /** | |
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
8610
diff
changeset
|
23 * @file libavcodec/h264_parser.c |
4975 | 24 * H.264 / AVC / MPEG4 part10 parser. |
25 * @author Michael Niedermayer <michaelni@gmx.at> | |
26 */ | |
27 | |
28 #include "parser.h" | |
29 #include "h264_parser.h" | |
8997 | 30 #include "h264data.h" |
31 #include "golomb.h" | |
4975 | 32 |
33 #include <assert.h> | |
34 | |
35 | |
36 int ff_h264_find_frame_end(H264Context *h, const uint8_t *buf, int buf_size) | |
37 { | |
38 int i; | |
39 uint32_t state; | |
40 ParseContext *pc = &(h->s.parse_context); | |
41 //printf("first %02X%02X%02X%02X\n", buf[0], buf[1],buf[2],buf[3]); | |
42 // mb_addr= pc->mb_addr - 1; | |
43 state= pc->state; | |
44 if(state>13) | |
45 state= 7; | |
46 | |
47 for(i=0; i<buf_size; i++){ | |
48 if(state==7){ | |
8590 | 49 #if HAVE_FAST_UNALIGNED |
8503 | 50 /* we check i<buf_size instead of i+3/7 because its simpler |
51 * and there should be FF_INPUT_BUFFER_PADDING_SIZE bytes at the end | |
52 */ | |
8590 | 53 # if HAVE_FAST_64BIT |
8763 | 54 while(i<buf_size && !((~*(const uint64_t*)(buf+i) & (*(const uint64_t*)(buf+i) - 0x0101010101010101ULL)) & 0x8080808080808080ULL)) |
8442 | 55 i+=8; |
56 # else | |
8763 | 57 while(i<buf_size && !((~*(const uint32_t*)(buf+i) & (*(const uint32_t*)(buf+i) - 0x01010101U)) & 0x80808080U)) |
8442 | 58 i+=4; |
59 # endif | |
60 #endif | |
4975 | 61 for(; i<buf_size; i++){ |
62 if(!buf[i]){ | |
63 state=2; | |
64 break; | |
65 } | |
66 } | |
67 }else if(state<=2){ | |
68 if(buf[i]==1) state^= 5; //2->7, 1->4, 0->5 | |
69 else if(buf[i]) state = 7; | |
70 else state>>=1; //2->1, 1->0, 0->0 | |
71 }else if(state<=5){ | |
72 int v= buf[i] & 0x1F; | |
9180 | 73 if(v==6 || v==7 || v==8 || v==9){ |
4975 | 74 if(pc->frame_start_found){ |
75 i++; | |
7986 | 76 goto found; |
4975 | 77 } |
78 }else if(v==1 || v==2 || v==5){ | |
79 if(pc->frame_start_found){ | |
80 state+=8; | |
81 continue; | |
82 }else | |
83 pc->frame_start_found = 1; | |
84 } | |
85 state= 7; | |
86 }else{ | |
87 if(buf[i] & 0x80) | |
88 goto found; | |
89 state= 7; | |
90 } | |
91 } | |
92 pc->state= state; | |
93 return END_NOT_FOUND; | |
7986 | 94 |
95 found: | |
96 pc->state=7; | |
97 pc->frame_start_found= 0; | |
98 return i-(state&5); | |
4975 | 99 } |
100 | |
8997 | 101 /*! |
102 * Parse NAL units of found picture and decode some basic information. | |
103 * | |
104 * @param s parser context. | |
105 * @param avctx codec context. | |
106 * @param buf buffer with field/frame data. | |
107 * @param buf_size size of the buffer. | |
108 */ | |
109 static inline int parse_nal_units(AVCodecParserContext *s, | |
110 AVCodecContext *avctx, | |
111 const uint8_t *buf, int buf_size) | |
112 { | |
113 H264Context *h = s->priv_data; | |
114 const uint8_t *buf_end = buf + buf_size; | |
8999
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
115 unsigned int pps_id; |
8997 | 116 unsigned int slice_type; |
9424 | 117 int state = -1; |
8997 | 118 const uint8_t *ptr; |
119 | |
120 /* set some sane default values */ | |
121 s->pict_type = FF_I_TYPE; | |
8998 | 122 s->key_frame = 0; |
8997 | 123 |
124 h->s.avctx= avctx; | |
8998 | 125 h->sei_recovery_frame_cnt = -1; |
9039 | 126 h->sei_dpb_output_delay = 0; |
127 h->sei_cpb_removal_delay = -1; | |
128 h->sei_buffering_period_present = 0; | |
8997 | 129 |
130 for(;;) { | |
131 int src_length, dst_length, consumed; | |
132 buf = ff_find_start_code(buf, buf_end, &state); | |
133 if(buf >= buf_end) | |
134 break; | |
135 --buf; | |
136 src_length = buf_end - buf; | |
137 switch (state & 0x1f) { | |
138 case NAL_SLICE: | |
139 case NAL_IDR_SLICE: | |
140 // Do not walk the whole buffer just to decode slice header | |
141 if (src_length > 20) | |
142 src_length = 20; | |
143 break; | |
144 } | |
145 ptr= ff_h264_decode_nal(h, buf, &dst_length, &consumed, src_length); | |
146 if (ptr==NULL || dst_length < 0) | |
147 break; | |
148 | |
149 init_get_bits(&h->s.gb, ptr, 8*dst_length); | |
150 switch(h->nal_unit_type) { | |
151 case NAL_SPS: | |
152 ff_h264_decode_seq_parameter_set(h); | |
153 break; | |
154 case NAL_PPS: | |
155 ff_h264_decode_picture_parameter_set(h, h->s.gb.size_in_bits); | |
156 break; | |
157 case NAL_SEI: | |
158 ff_h264_decode_sei(h); | |
159 break; | |
160 case NAL_IDR_SLICE: | |
8998 | 161 s->key_frame = 1; |
162 /* fall through */ | |
8997 | 163 case NAL_SLICE: |
164 get_ue_golomb(&h->s.gb); // skip first_mb_in_slice | |
165 slice_type = get_ue_golomb_31(&h->s.gb); | |
166 s->pict_type = golomb_to_pict_type[slice_type % 5]; | |
8998 | 167 if (h->sei_recovery_frame_cnt >= 0) { |
168 /* key frame, since recovery_frame_cnt is set */ | |
169 s->key_frame = 1; | |
170 } | |
8999
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
171 pps_id= get_ue_golomb(&h->s.gb); |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
172 if(pps_id>=MAX_PPS_COUNT) { |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
173 av_log(h->s.avctx, AV_LOG_ERROR, "pps_id out of range\n"); |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
174 return -1; |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
175 } |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
176 if(!h->pps_buffers[pps_id]) { |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
177 av_log(h->s.avctx, AV_LOG_ERROR, "non-existing PPS referenced\n"); |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
178 return -1; |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
179 } |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
180 h->pps= *h->pps_buffers[pps_id]; |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
181 if(!h->sps_buffers[h->pps.sps_id]) { |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
182 av_log(h->s.avctx, AV_LOG_ERROR, "non-existing SPS referenced\n"); |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
183 return -1; |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
184 } |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
185 h->sps = *h->sps_buffers[h->pps.sps_id]; |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
186 h->frame_num = get_bits(&h->s.gb, h->sps.log2_max_frame_num); |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
187 |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
188 if(h->sps.frame_mbs_only_flag){ |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
189 h->s.picture_structure= PICT_FRAME; |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
190 }else{ |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
191 if(get_bits1(&h->s.gb)) { //field_pic_flag |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
192 h->s.picture_structure= PICT_TOP_FIELD + get_bits1(&h->s.gb); //bottom_field_flag |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
193 } else { |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
194 h->s.picture_structure= PICT_FRAME; |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
195 } |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
196 } |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
197 |
9000
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
198 if(h->sps.pic_struct_present_flag) { |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
199 switch (h->sei_pic_struct) { |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
200 case SEI_PIC_STRUCT_TOP_FIELD: |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
201 case SEI_PIC_STRUCT_BOTTOM_FIELD: |
9035 | 202 s->repeat_pict = 0; |
9000
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
203 break; |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
204 case SEI_PIC_STRUCT_FRAME: |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
205 case SEI_PIC_STRUCT_TOP_BOTTOM: |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
206 case SEI_PIC_STRUCT_BOTTOM_TOP: |
9035 | 207 s->repeat_pict = 1; |
9000
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
208 break; |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
209 case SEI_PIC_STRUCT_TOP_BOTTOM_TOP: |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
210 case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
211 s->repeat_pict = 2; |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
212 break; |
9035 | 213 case SEI_PIC_STRUCT_FRAME_DOUBLING: |
214 s->repeat_pict = 3; | |
215 break; | |
9000
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
216 case SEI_PIC_STRUCT_FRAME_TRIPLING: |
9035 | 217 s->repeat_pict = 5; |
9000
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
218 break; |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
219 default: |
9035 | 220 s->repeat_pict = h->s.picture_structure == PICT_FRAME ? 1 : 0; |
9000
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
221 break; |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
222 } |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
223 } else { |
9035 | 224 s->repeat_pict = h->s.picture_structure == PICT_FRAME ? 1 : 0; |
9000
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
225 } |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
226 |
8997 | 227 return 0; /* no need to evaluate the rest */ |
228 } | |
229 buf += consumed; | |
230 } | |
231 /* didn't find a picture! */ | |
232 av_log(h->s.avctx, AV_LOG_ERROR, "missing picture in access unit\n"); | |
233 return -1; | |
234 } | |
235 | |
4975 | 236 static int h264_parse(AVCodecParserContext *s, |
237 AVCodecContext *avctx, | |
238 const uint8_t **poutbuf, int *poutbuf_size, | |
239 const uint8_t *buf, int buf_size) | |
240 { | |
241 H264Context *h = s->priv_data; | |
242 ParseContext *pc = &h->s.parse_context; | |
243 int next; | |
244 | |
245 if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ | |
246 next= buf_size; | |
247 }else{ | |
248 next= ff_h264_find_frame_end(h, buf, buf_size); | |
249 | |
250 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { | |
251 *poutbuf = NULL; | |
252 *poutbuf_size = 0; | |
253 return buf_size; | |
254 } | |
255 | |
256 if(next<0 && next != END_NOT_FOUND){ | |
257 assert(pc->last_index + next >= 0 ); | |
258 ff_h264_find_frame_end(h, &pc->buffer[pc->last_index + next], -next); //update state | |
259 } | |
8997 | 260 |
261 parse_nal_units(s, avctx, buf, buf_size); | |
9039 | 262 |
9056
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
263 if (h->sei_cpb_removal_delay >= 0) { |
9057 | 264 s->dts_sync_point = h->sei_buffering_period_present; |
265 s->dts_ref_dts_delta = h->sei_cpb_removal_delay; | |
266 s->pts_dts_delta = h->sei_dpb_output_delay; | |
9056
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
267 } else { |
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
268 s->dts_sync_point = INT_MIN; |
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
269 s->dts_ref_dts_delta = INT_MIN; |
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
270 s->pts_dts_delta = INT_MIN; |
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
271 } |
4975 | 272 } |
273 | |
274 *poutbuf = buf; | |
275 *poutbuf_size = buf_size; | |
276 return next; | |
277 } | |
278 | |
279 static int h264_split(AVCodecContext *avctx, | |
280 const uint8_t *buf, int buf_size) | |
281 { | |
282 int i; | |
283 uint32_t state = -1; | |
284 int has_sps= 0; | |
285 | |
286 for(i=0; i<=buf_size; i++){ | |
287 if((state&0xFFFFFF1F) == 0x107) | |
288 has_sps=1; | |
289 /* if((state&0xFFFFFF1F) == 0x101 || (state&0xFFFFFF1F) == 0x102 || (state&0xFFFFFF1F) == 0x105){ | |
290 }*/ | |
291 if((state&0xFFFFFF00) == 0x100 && (state&0xFFFFFF1F) != 0x107 && (state&0xFFFFFF1F) != 0x108 && (state&0xFFFFFF1F) != 0x109){ | |
292 if(has_sps){ | |
293 while(i>4 && buf[i-5]==0) i--; | |
294 return i-4; | |
295 } | |
296 } | |
297 if (i<buf_size) | |
298 state= (state<<8) | buf[i]; | |
299 } | |
300 return 0; | |
301 } | |
302 | |
7991 | 303 static void close(AVCodecParserContext *s) |
7989
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
304 { |
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
305 H264Context *h = s->priv_data; |
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
306 ParseContext *pc = &h->s.parse_context; |
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
307 |
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
308 av_free(pc->buffer); |
9380
54e650136c87
Add a ff_h264_free_context function and call it from the H.264 parser.
reimar
parents:
9180
diff
changeset
|
309 ff_h264_free_context(h); |
7989
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
310 } |
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
311 |
4975 | 312 |
313 AVCodecParser h264_parser = { | |
8610 | 314 { CODEC_ID_H264 }, |
4975 | 315 sizeof(H264Context), |
316 NULL, | |
317 h264_parse, | |
7989
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
318 close, |
4975 | 319 h264_split, |
320 }; |