Mercurial > libavcodec.hg
annotate h264_parser.c @ 11816:7c2369ec6faa libavcodec
ARM: check struct offsets only when they are used
The offsets differ depending on configuration, so only check them when
they will actually be used. Presently, this is when NEON is enabled.
author | mru |
---|---|
date | Wed, 02 Jun 2010 22:05:25 +0000 |
parents | 51abd780bda6 |
children | cabcd751b1e5 |
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 /** | |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11047
diff
changeset
|
23 * @file |
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 |
11047 | 188 avctx->profile = h->sps.profile_idc; |
189 avctx->level = h->sps.level_idc; | |
190 | |
8999
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
191 if(h->sps.frame_mbs_only_flag){ |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
192 h->s.picture_structure= PICT_FRAME; |
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 if(get_bits1(&h->s.gb)) { //field_pic_flag |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
195 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
|
196 } else { |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
197 h->s.picture_structure= PICT_FRAME; |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
198 } |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
199 } |
f701dab6a62d
Set context variable picture_structure in H264 parser.
cehoyos
parents:
8998
diff
changeset
|
200 |
9000
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
201 if(h->sps.pic_struct_present_flag) { |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
202 switch (h->sei_pic_struct) { |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
203 case SEI_PIC_STRUCT_TOP_FIELD: |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
204 case SEI_PIC_STRUCT_BOTTOM_FIELD: |
9035 | 205 s->repeat_pict = 0; |
9000
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
206 break; |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
207 case SEI_PIC_STRUCT_FRAME: |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
208 case SEI_PIC_STRUCT_TOP_BOTTOM: |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
209 case SEI_PIC_STRUCT_BOTTOM_TOP: |
9035 | 210 s->repeat_pict = 1; |
9000
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
211 break; |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
212 case SEI_PIC_STRUCT_TOP_BOTTOM_TOP: |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
213 case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
214 s->repeat_pict = 2; |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
215 break; |
9035 | 216 case SEI_PIC_STRUCT_FRAME_DOUBLING: |
217 s->repeat_pict = 3; | |
218 break; | |
9000
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
219 case SEI_PIC_STRUCT_FRAME_TRIPLING: |
9035 | 220 s->repeat_pict = 5; |
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 default: |
9035 | 223 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
|
224 break; |
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 } else { |
9035 | 227 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
|
228 } |
78afc2990d00
Use context variable repeat_pict for frame duration computation and
cehoyos
parents:
8999
diff
changeset
|
229 |
8997 | 230 return 0; /* no need to evaluate the rest */ |
231 } | |
232 buf += consumed; | |
233 } | |
234 /* didn't find a picture! */ | |
235 av_log(h->s.avctx, AV_LOG_ERROR, "missing picture in access unit\n"); | |
236 return -1; | |
237 } | |
238 | |
4975 | 239 static int h264_parse(AVCodecParserContext *s, |
240 AVCodecContext *avctx, | |
241 const uint8_t **poutbuf, int *poutbuf_size, | |
242 const uint8_t *buf, int buf_size) | |
243 { | |
244 H264Context *h = s->priv_data; | |
245 ParseContext *pc = &h->s.parse_context; | |
246 int next; | |
247 | |
11791
51abd780bda6
Cleanup prev commit, flag variable should start with 0
hyc
parents:
11790
diff
changeset
|
248 if (!h->got_first) { |
51abd780bda6
Cleanup prev commit, flag variable should start with 0
hyc
parents:
11790
diff
changeset
|
249 h->got_first = 1; |
11790 | 250 if (avctx->extradata_size) { |
251 h->s.avctx = avctx; | |
252 ff_h264_decode_extradata(h); | |
253 } | |
254 } | |
255 | |
4975 | 256 if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ |
257 next= buf_size; | |
258 }else{ | |
259 next= ff_h264_find_frame_end(h, buf, buf_size); | |
260 | |
261 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { | |
262 *poutbuf = NULL; | |
263 *poutbuf_size = 0; | |
264 return buf_size; | |
265 } | |
266 | |
267 if(next<0 && next != END_NOT_FOUND){ | |
268 assert(pc->last_index + next >= 0 ); | |
269 ff_h264_find_frame_end(h, &pc->buffer[pc->last_index + next], -next); //update state | |
270 } | |
8997 | 271 |
272 parse_nal_units(s, avctx, buf, buf_size); | |
9039 | 273 |
9056
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
274 if (h->sei_cpb_removal_delay >= 0) { |
9057 | 275 s->dts_sync_point = h->sei_buffering_period_present; |
276 s->dts_ref_dts_delta = h->sei_cpb_removal_delay; | |
277 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
|
278 } else { |
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
279 s->dts_sync_point = INT_MIN; |
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
280 s->dts_ref_dts_delta = INT_MIN; |
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
281 s->pts_dts_delta = INT_MIN; |
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
282 } |
11770
6d58a4f5e455
Add an AVSTREAM_PARSE_FULL_ONCE parsing mode to parse headers and combine packets once and only once.
alexc
parents:
11644
diff
changeset
|
283 if (s->flags & PARSER_FLAG_ONCE) { |
6d58a4f5e455
Add an AVSTREAM_PARSE_FULL_ONCE parsing mode to parse headers and combine packets once and only once.
alexc
parents:
11644
diff
changeset
|
284 s->flags &= PARSER_FLAG_COMPLETE_FRAMES; |
6d58a4f5e455
Add an AVSTREAM_PARSE_FULL_ONCE parsing mode to parse headers and combine packets once and only once.
alexc
parents:
11644
diff
changeset
|
285 } |
4975 | 286 } |
287 | |
288 *poutbuf = buf; | |
289 *poutbuf_size = buf_size; | |
290 return next; | |
291 } | |
292 | |
293 static int h264_split(AVCodecContext *avctx, | |
294 const uint8_t *buf, int buf_size) | |
295 { | |
296 int i; | |
297 uint32_t state = -1; | |
298 int has_sps= 0; | |
299 | |
300 for(i=0; i<=buf_size; i++){ | |
301 if((state&0xFFFFFF1F) == 0x107) | |
302 has_sps=1; | |
303 /* if((state&0xFFFFFF1F) == 0x101 || (state&0xFFFFFF1F) == 0x102 || (state&0xFFFFFF1F) == 0x105){ | |
304 }*/ | |
305 if((state&0xFFFFFF00) == 0x100 && (state&0xFFFFFF1F) != 0x107 && (state&0xFFFFFF1F) != 0x108 && (state&0xFFFFFF1F) != 0x109){ | |
306 if(has_sps){ | |
307 while(i>4 && buf[i-5]==0) i--; | |
308 return i-4; | |
309 } | |
310 } | |
311 if (i<buf_size) | |
312 state= (state<<8) | buf[i]; | |
313 } | |
314 return 0; | |
315 } | |
316 | |
7991 | 317 static void close(AVCodecParserContext *s) |
7989
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
318 { |
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
319 H264Context *h = s->priv_data; |
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
320 ParseContext *pc = &h->s.parse_context; |
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
321 |
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
322 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
|
323 ff_h264_free_context(h); |
7989
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
324 } |
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
325 |
11043
916df4ea4e64
Initialize thread_context[0] with h264 parser context.
benoit
parents:
9424
diff
changeset
|
326 static int init(AVCodecParserContext *s) |
916df4ea4e64
Initialize thread_context[0] with h264 parser context.
benoit
parents:
9424
diff
changeset
|
327 { |
916df4ea4e64
Initialize thread_context[0] with h264 parser context.
benoit
parents:
9424
diff
changeset
|
328 H264Context *h = s->priv_data; |
916df4ea4e64
Initialize thread_context[0] with h264 parser context.
benoit
parents:
9424
diff
changeset
|
329 h->thread_context[0] = h; |
916df4ea4e64
Initialize thread_context[0] with h264 parser context.
benoit
parents:
9424
diff
changeset
|
330 return 0; |
916df4ea4e64
Initialize thread_context[0] with h264 parser context.
benoit
parents:
9424
diff
changeset
|
331 } |
4975 | 332 |
333 AVCodecParser h264_parser = { | |
8610 | 334 { CODEC_ID_H264 }, |
4975 | 335 sizeof(H264Context), |
11043
916df4ea4e64
Initialize thread_context[0] with h264 parser context.
benoit
parents:
9424
diff
changeset
|
336 init, |
4975 | 337 h264_parse, |
7989
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
338 close, |
4975 | 339 h264_split, |
340 }; |