annotate h264_parser.c @ 8520:a0164882aa38 libavcodec

Generic metadata API. avi is updated as example. No version bump, the API still might change slightly ... No update to ffmpeg.c as requested by aurel.
author michael
date Sun, 04 Jan 2009 18:48:37 +0000
parents 7c82ed8d4824
children f8c091bb5779
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4975
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
1 /*
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
2 * H.26L/H.264/AVC/JVT/14496-10/... parser
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
3 * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
4 *
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
5 * This file is part of FFmpeg.
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
6 *
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
11 *
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
15 * Lesser General Public License for more details.
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
16 *
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
20 */
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
21
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
22 /**
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
23 * @file h264_parser.c
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
24 * H.264 / AVC / MPEG4 part10 parser.
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
25 * @author Michael Niedermayer <michaelni@gmx.at>
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
26 */
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
27
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
28 #include "parser.h"
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
29 #include "h264_parser.h"
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
30
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
31 #include <assert.h>
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
32
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
33
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
34 int ff_h264_find_frame_end(H264Context *h, const uint8_t *buf, int buf_size)
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
35 {
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
36 int i;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
37 uint32_t state;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
38 ParseContext *pc = &(h->s.parse_context);
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
39 //printf("first %02X%02X%02X%02X\n", buf[0], buf[1],buf[2],buf[3]);
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
40 // mb_addr= pc->mb_addr - 1;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
41 state= pc->state;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
42 if(state>13)
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
43 state= 7;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
44
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
45 for(i=0; i<buf_size; i++){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
46 if(state==7){
8442
60be1c7d8345 Make h264 parser 50% faster.
michael
parents: 7991
diff changeset
47 #ifdef HAVE_FAST_UNALIGNED
8503
7c82ed8d4824 Explain the lack of +3/7
michael
parents: 8442
diff changeset
48 /* we check i<buf_size instead of i+3/7 because its simpler
7c82ed8d4824 Explain the lack of +3/7
michael
parents: 8442
diff changeset
49 * and there should be FF_INPUT_BUFFER_PADDING_SIZE bytes at the end
7c82ed8d4824 Explain the lack of +3/7
michael
parents: 8442
diff changeset
50 */
8442
60be1c7d8345 Make h264 parser 50% faster.
michael
parents: 7991
diff changeset
51 # ifdef HAVE_FAST_64BIT
60be1c7d8345 Make h264 parser 50% faster.
michael
parents: 7991
diff changeset
52 while(i<buf_size && !((~*(uint64_t*)(buf+i) & (*(uint64_t*)(buf+i) - 0x0101010101010101ULL)) & 0x8080808080808080ULL))
60be1c7d8345 Make h264 parser 50% faster.
michael
parents: 7991
diff changeset
53 i+=8;
60be1c7d8345 Make h264 parser 50% faster.
michael
parents: 7991
diff changeset
54 # else
60be1c7d8345 Make h264 parser 50% faster.
michael
parents: 7991
diff changeset
55 while(i<buf_size && !((~*(uint32_t*)(buf+i) & (*(uint32_t*)(buf+i) - 0x01010101U)) & 0x80808080U))
60be1c7d8345 Make h264 parser 50% faster.
michael
parents: 7991
diff changeset
56 i+=4;
60be1c7d8345 Make h264 parser 50% faster.
michael
parents: 7991
diff changeset
57 # endif
60be1c7d8345 Make h264 parser 50% faster.
michael
parents: 7991
diff changeset
58 #endif
4975
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
59 for(; i<buf_size; i++){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
60 if(!buf[i]){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
61 state=2;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
62 break;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
63 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
64 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
65 }else if(state<=2){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
66 if(buf[i]==1) state^= 5; //2->7, 1->4, 0->5
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
67 else if(buf[i]) state = 7;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
68 else state>>=1; //2->1, 1->0, 0->0
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
69 }else if(state<=5){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
70 int v= buf[i] & 0x1F;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
71 if(v==7 || v==8 || v==9){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
72 if(pc->frame_start_found){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
73 i++;
7986
38d577c3cb60 fix warning reported by Intel C compiler:
gpoirier
parents: 5215
diff changeset
74 goto found;
4975
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
75 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
76 }else if(v==1 || v==2 || v==5){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
77 if(pc->frame_start_found){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
78 state+=8;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
79 continue;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
80 }else
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
81 pc->frame_start_found = 1;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
82 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
83 state= 7;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
84 }else{
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
85 if(buf[i] & 0x80)
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
86 goto found;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
87 state= 7;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
88 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
89 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
90 pc->state= state;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
91 return END_NOT_FOUND;
7986
38d577c3cb60 fix warning reported by Intel C compiler:
gpoirier
parents: 5215
diff changeset
92
38d577c3cb60 fix warning reported by Intel C compiler:
gpoirier
parents: 5215
diff changeset
93 found:
38d577c3cb60 fix warning reported by Intel C compiler:
gpoirier
parents: 5215
diff changeset
94 pc->state=7;
38d577c3cb60 fix warning reported by Intel C compiler:
gpoirier
parents: 5215
diff changeset
95 pc->frame_start_found= 0;
38d577c3cb60 fix warning reported by Intel C compiler:
gpoirier
parents: 5215
diff changeset
96 return i-(state&5);
4975
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
97 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
98
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
99 static int h264_parse(AVCodecParserContext *s,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
100 AVCodecContext *avctx,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
101 const uint8_t **poutbuf, int *poutbuf_size,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
102 const uint8_t *buf, int buf_size)
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
103 {
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
104 H264Context *h = s->priv_data;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
105 ParseContext *pc = &h->s.parse_context;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
106 int next;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
107
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
108 if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
109 next= buf_size;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
110 }else{
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
111 next= ff_h264_find_frame_end(h, buf, buf_size);
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
112
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
113 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
114 *poutbuf = NULL;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
115 *poutbuf_size = 0;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
116 return buf_size;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
117 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
118
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
119 if(next<0 && next != END_NOT_FOUND){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
120 assert(pc->last_index + next >= 0 );
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
121 ff_h264_find_frame_end(h, &pc->buffer[pc->last_index + next], -next); //update state
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
122 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
123 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
124
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
125 *poutbuf = buf;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
126 *poutbuf_size = buf_size;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
127 return next;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
128 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
129
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
130 static int h264_split(AVCodecContext *avctx,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
131 const uint8_t *buf, int buf_size)
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
132 {
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
133 int i;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
134 uint32_t state = -1;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
135 int has_sps= 0;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
136
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
137 for(i=0; i<=buf_size; i++){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
138 if((state&0xFFFFFF1F) == 0x107)
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
139 has_sps=1;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
140 /* if((state&0xFFFFFF1F) == 0x101 || (state&0xFFFFFF1F) == 0x102 || (state&0xFFFFFF1F) == 0x105){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
141 }*/
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
142 if((state&0xFFFFFF00) == 0x100 && (state&0xFFFFFF1F) != 0x107 && (state&0xFFFFFF1F) != 0x108 && (state&0xFFFFFF1F) != 0x109){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
143 if(has_sps){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
144 while(i>4 && buf[i-5]==0) i--;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
145 return i-4;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
146 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
147 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
148 if (i<buf_size)
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
149 state= (state<<8) | buf[i];
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
150 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
151 return 0;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
152 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
153
7991
a38b31a2ac52 100l forgot return type.
michael
parents: 7989
diff changeset
154 static void close(AVCodecParserContext *s)
7989
0607ff0877ff ff_parse_close() is not the correct function for H264Context.
michael
parents: 7986
diff changeset
155 {
0607ff0877ff ff_parse_close() is not the correct function for H264Context.
michael
parents: 7986
diff changeset
156 H264Context *h = s->priv_data;
0607ff0877ff ff_parse_close() is not the correct function for H264Context.
michael
parents: 7986
diff changeset
157 ParseContext *pc = &h->s.parse_context;
0607ff0877ff ff_parse_close() is not the correct function for H264Context.
michael
parents: 7986
diff changeset
158
0607ff0877ff ff_parse_close() is not the correct function for H264Context.
michael
parents: 7986
diff changeset
159 av_free(pc->buffer);
0607ff0877ff ff_parse_close() is not the correct function for H264Context.
michael
parents: 7986
diff changeset
160 }
0607ff0877ff ff_parse_close() is not the correct function for H264Context.
michael
parents: 7986
diff changeset
161
4975
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
162
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
163 AVCodecParser h264_parser = {
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
164 { CODEC_ID_H264 },
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
165 sizeof(H264Context),
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
166 NULL,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
167 h264_parse,
7989
0607ff0877ff ff_parse_close() is not the correct function for H264Context.
michael
parents: 7986
diff changeset
168 close,
4975
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
169 h264_split,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
170 };