Mercurial > libavcodec.hg
annotate h264_parser.c @ 11352:6e0af2cfdcfe libavcodec
Do MC and IDCT in coding (hilbert) order
This increases the slice size to 64 pixels, due to having to decode an
entire chroma superblock row per slice.
This can be up to 6% slower depending on clip and CPU, but is necessary
for future optimizations that gain significantly more than was lost.
author | conrad |
---|---|
date | Wed, 03 Mar 2010 23:27:40 +0000 |
parents | ec682347e19e |
children | 7dd2a45249a9 |
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 |
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 | |
248 if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ | |
249 next= buf_size; | |
250 }else{ | |
251 next= ff_h264_find_frame_end(h, buf, buf_size); | |
252 | |
253 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { | |
254 *poutbuf = NULL; | |
255 *poutbuf_size = 0; | |
256 return buf_size; | |
257 } | |
258 | |
259 if(next<0 && next != END_NOT_FOUND){ | |
260 assert(pc->last_index + next >= 0 ); | |
261 ff_h264_find_frame_end(h, &pc->buffer[pc->last_index + next], -next); //update state | |
262 } | |
8997 | 263 |
264 parse_nal_units(s, avctx, buf, buf_size); | |
9039 | 265 |
9056
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
266 if (h->sei_cpb_removal_delay >= 0) { |
9057 | 267 s->dts_sync_point = h->sei_buffering_period_present; |
268 s->dts_ref_dts_delta = h->sei_cpb_removal_delay; | |
269 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
|
270 } else { |
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
271 s->dts_sync_point = INT_MIN; |
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
272 s->dts_ref_dts_delta = INT_MIN; |
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
273 s->pts_dts_delta = INT_MIN; |
4180f20569c1
Initialize H264 parser context correctly if the optional SEI messages
cehoyos
parents:
9039
diff
changeset
|
274 } |
4975 | 275 } |
276 | |
277 *poutbuf = buf; | |
278 *poutbuf_size = buf_size; | |
279 return next; | |
280 } | |
281 | |
282 static int h264_split(AVCodecContext *avctx, | |
283 const uint8_t *buf, int buf_size) | |
284 { | |
285 int i; | |
286 uint32_t state = -1; | |
287 int has_sps= 0; | |
288 | |
289 for(i=0; i<=buf_size; i++){ | |
290 if((state&0xFFFFFF1F) == 0x107) | |
291 has_sps=1; | |
292 /* if((state&0xFFFFFF1F) == 0x101 || (state&0xFFFFFF1F) == 0x102 || (state&0xFFFFFF1F) == 0x105){ | |
293 }*/ | |
294 if((state&0xFFFFFF00) == 0x100 && (state&0xFFFFFF1F) != 0x107 && (state&0xFFFFFF1F) != 0x108 && (state&0xFFFFFF1F) != 0x109){ | |
295 if(has_sps){ | |
296 while(i>4 && buf[i-5]==0) i--; | |
297 return i-4; | |
298 } | |
299 } | |
300 if (i<buf_size) | |
301 state= (state<<8) | buf[i]; | |
302 } | |
303 return 0; | |
304 } | |
305 | |
7991 | 306 static void close(AVCodecParserContext *s) |
7989
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 H264Context *h = s->priv_data; |
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
309 ParseContext *pc = &h->s.parse_context; |
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 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
|
312 ff_h264_free_context(h); |
7989
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
313 } |
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
314 |
11043
916df4ea4e64
Initialize thread_context[0] with h264 parser context.
benoit
parents:
9424
diff
changeset
|
315 static int init(AVCodecParserContext *s) |
916df4ea4e64
Initialize thread_context[0] with h264 parser context.
benoit
parents:
9424
diff
changeset
|
316 { |
916df4ea4e64
Initialize thread_context[0] with h264 parser context.
benoit
parents:
9424
diff
changeset
|
317 H264Context *h = s->priv_data; |
916df4ea4e64
Initialize thread_context[0] with h264 parser context.
benoit
parents:
9424
diff
changeset
|
318 h->thread_context[0] = h; |
916df4ea4e64
Initialize thread_context[0] with h264 parser context.
benoit
parents:
9424
diff
changeset
|
319 return 0; |
916df4ea4e64
Initialize thread_context[0] with h264 parser context.
benoit
parents:
9424
diff
changeset
|
320 } |
4975 | 321 |
322 AVCodecParser h264_parser = { | |
8610 | 323 { CODEC_ID_H264 }, |
4975 | 324 sizeof(H264Context), |
11043
916df4ea4e64
Initialize thread_context[0] with h264 parser context.
benoit
parents:
9424
diff
changeset
|
325 init, |
4975 | 326 h264_parse, |
7989
0607ff0877ff
ff_parse_close() is not the correct function for H264Context.
michael
parents:
7986
diff
changeset
|
327 close, |
4975 | 328 h264_split, |
329 }; |