annotate parser.c @ 2071:41d30bae5019 libavcodec

attempt to create some separation in the FLAC system with respect to demuxer and decoder layers by enabling the FLAC decoder to decode data without needing the entire file, from start to finish
author melanson
date Thu, 10 Jun 2004 04:13:43 +0000
parents f796043935f3
children bec4623c2201
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
1 /*
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
2 * Audio and Video frame extraction
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
3 * Copyright (c) 2003 Fabrice Bellard.
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
4 * Copyright (c) 2003 Michael Niedermayer.
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
5 *
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
6 * This library is free software; you can redistribute it and/or
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
7 * modify it under the terms of the GNU Lesser General Public
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
8 * License as published by the Free Software Foundation; either
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
9 * version 2 of the License, or (at your option) any later version.
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
10 *
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
11 * This library is distributed in the hope that it will be useful,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
14 * Lesser General Public License for more details.
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
15 *
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
16 * You should have received a copy of the GNU Lesser General Public
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
17 * License along with this library; if not, write to the Free Software
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
19 */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
20 #include "avcodec.h"
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
21 #include "mpegvideo.h"
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
22 #include "mpegaudio.h"
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
23
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
24 AVCodecParser *av_first_parser = NULL;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
25
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
26 void av_register_codec_parser(AVCodecParser *parser)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
27 {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
28 parser->next = av_first_parser;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
29 av_first_parser = parser;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
30 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
31
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
32 AVCodecParserContext *av_parser_init(int codec_id)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
33 {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
34 AVCodecParserContext *s;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
35 AVCodecParser *parser;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
36 int ret;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
37
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
38 for(parser = av_first_parser; parser != NULL; parser = parser->next) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
39 if (parser->codec_ids[0] == codec_id ||
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
40 parser->codec_ids[1] == codec_id ||
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
41 parser->codec_ids[2] == codec_id)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
42 goto found;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
43 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
44 return NULL;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
45 found:
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
46 s = av_mallocz(sizeof(AVCodecParserContext));
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
47 if (!s)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
48 return NULL;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
49 s->parser = parser;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
50 s->priv_data = av_mallocz(parser->priv_data_size);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
51 if (!s->priv_data) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
52 av_free(s);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
53 return NULL;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
54 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
55 if (parser->parser_init) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
56 ret = parser->parser_init(s);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
57 if (ret != 0) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
58 av_free(s->priv_data);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
59 av_free(s);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
60 return NULL;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
61 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
62 }
2030
f796043935f3 mpeg audio timestamp fix
michael
parents: 2024
diff changeset
63 s->fetch_timestamp=1;
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
64 return s;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
65 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
66
1694
13169235c306 added End Of File handling to return last picture for MPEG1/2/4
bellard
parents: 1681
diff changeset
67 /* NOTE: buf_size == 0 is used to signal EOF so that the last frame
13169235c306 added End Of File handling to return last picture for MPEG1/2/4
bellard
parents: 1681
diff changeset
68 can be returned if necessary */
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
69 int av_parser_parse(AVCodecParserContext *s,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
70 AVCodecContext *avctx,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
71 uint8_t **poutbuf, int *poutbuf_size,
1696
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
72 const uint8_t *buf, int buf_size,
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
73 int64_t pts, int64_t dts)
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
74 {
1696
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
75 int index, i, k;
1694
13169235c306 added End Of File handling to return last picture for MPEG1/2/4
bellard
parents: 1681
diff changeset
76 uint8_t dummy_buf[FF_INPUT_BUFFER_PADDING_SIZE];
13169235c306 added End Of File handling to return last picture for MPEG1/2/4
bellard
parents: 1681
diff changeset
77
13169235c306 added End Of File handling to return last picture for MPEG1/2/4
bellard
parents: 1681
diff changeset
78 if (buf_size == 0) {
13169235c306 added End Of File handling to return last picture for MPEG1/2/4
bellard
parents: 1681
diff changeset
79 /* padding is always necessary even if EOF, so we add it here */
13169235c306 added End Of File handling to return last picture for MPEG1/2/4
bellard
parents: 1681
diff changeset
80 memset(dummy_buf, 0, sizeof(dummy_buf));
13169235c306 added End Of File handling to return last picture for MPEG1/2/4
bellard
parents: 1681
diff changeset
81 buf = dummy_buf;
1696
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
82 } else {
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
83 /* add a new packet descriptor */
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
84 k = (s->cur_frame_start_index + 1) & (AV_PARSER_PTS_NB - 1);
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
85 s->cur_frame_start_index = k;
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
86 s->cur_frame_offset[k] = s->cur_offset;
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
87 s->cur_frame_pts[k] = pts;
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
88 s->cur_frame_dts[k] = dts;
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
89
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
90 /* fill first PTS/DTS */
2030
f796043935f3 mpeg audio timestamp fix
michael
parents: 2024
diff changeset
91 if (s->fetch_timestamp){
f796043935f3 mpeg audio timestamp fix
michael
parents: 2024
diff changeset
92 s->fetch_timestamp=0;
1696
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
93 s->last_pts = pts;
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
94 s->last_dts = dts;
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
95 }
1694
13169235c306 added End Of File handling to return last picture for MPEG1/2/4
bellard
parents: 1681
diff changeset
96 }
13169235c306 added End Of File handling to return last picture for MPEG1/2/4
bellard
parents: 1681
diff changeset
97
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
98 /* WARNING: the returned index can be negative */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
99 index = s->parser->parser_parse(s, avctx, poutbuf, poutbuf_size, buf, buf_size);
2030
f796043935f3 mpeg audio timestamp fix
michael
parents: 2024
diff changeset
100 //av_log(NULL, AV_LOG_DEBUG, "parser: in:%lld, %lld, out:%lld, %lld, in:%d out:%d %d\n", pts, dts, s->last_pts, s->last_dts, buf_size, *poutbuf_size, avctx->codec_id);
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
101 /* update the file pointer */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
102 if (*poutbuf_size) {
1696
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
103 /* fill the data for the current frame */
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
104 s->frame_offset = s->last_frame_offset;
1696
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
105 s->pts = s->last_pts;
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
106 s->dts = s->last_dts;
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
107
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
108 /* offset of the next frame */
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
109 s->last_frame_offset = s->cur_offset + index;
1696
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
110 /* find the packet in which the new frame starts. It
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
111 is tricky because of MPEG video start codes
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
112 which can begin in one packet and finish in
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
113 another packet. In the worst case, an MPEG
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
114 video start code could be in 4 different
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
115 packets. */
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
116 k = s->cur_frame_start_index;
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
117 for(i = 0; i < AV_PARSER_PTS_NB; i++) {
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
118 if (s->last_frame_offset >= s->cur_frame_offset[k])
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
119 break;
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
120 k = (k - 1) & (AV_PARSER_PTS_NB - 1);
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
121 }
2030
f796043935f3 mpeg audio timestamp fix
michael
parents: 2024
diff changeset
122
1696
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
123 s->last_pts = s->cur_frame_pts[k];
f5af91b8be17 pts and dts support in parser API
bellard
parents: 1694
diff changeset
124 s->last_dts = s->cur_frame_dts[k];
2030
f796043935f3 mpeg audio timestamp fix
michael
parents: 2024
diff changeset
125
f796043935f3 mpeg audio timestamp fix
michael
parents: 2024
diff changeset
126 /* some parsers tell us the packet size even before seeing the first byte of the next packet,
f796043935f3 mpeg audio timestamp fix
michael
parents: 2024
diff changeset
127 so the next pts/dts is in the next chunk */
f796043935f3 mpeg audio timestamp fix
michael
parents: 2024
diff changeset
128 if(index == buf_size){
f796043935f3 mpeg audio timestamp fix
michael
parents: 2024
diff changeset
129 s->fetch_timestamp=1;
f796043935f3 mpeg audio timestamp fix
michael
parents: 2024
diff changeset
130 }
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
131 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
132 if (index < 0)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
133 index = 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
134 s->cur_offset += index;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
135 return index;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
136 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
137
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
138 void av_parser_close(AVCodecParserContext *s)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
139 {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
140 if (s->parser->parser_close)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
141 s->parser->parser_close(s);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
142 av_free(s->priv_data);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
143 av_free(s);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
144 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
145
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
146 /*****************************************************/
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
147
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
148 //#define END_NOT_FOUND (-100)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
149
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
150 #define PICTURE_START_CODE 0x00000100
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
151 #define SEQ_START_CODE 0x000001b3
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
152 #define EXT_START_CODE 0x000001b5
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
153 #define SLICE_MIN_START_CODE 0x00000101
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
154 #define SLICE_MAX_START_CODE 0x000001af
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
155
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
156 typedef struct ParseContext1{
1988
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
157 ParseContext pc;
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
158 /* XXX/FIXME PC1 vs. PC */
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
159 /* MPEG2 specific */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
160 int frame_rate;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
161 int progressive_sequence;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
162 int width, height;
1614
6c82ef97d3e6 also parse extradata for MPEG4
bellard
parents: 1613
diff changeset
163
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
164 /* XXX: suppress that, needed by MPEG4 */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
165 MpegEncContext *enc;
1614
6c82ef97d3e6 also parse extradata for MPEG4
bellard
parents: 1613
diff changeset
166 int first_picture;
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
167 } ParseContext1;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
168
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
169 /**
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
170 * combines the (truncated) bitstream to a complete frame
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
171 * @returns -1 if no complete frame could be created
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
172 */
1988
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
173 int ff_combine_frame(ParseContext *pc, int next, uint8_t **buf, int *buf_size)
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
174 {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
175 #if 0
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
176 if(pc->overread){
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
177 printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
178 printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
179 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
180 #endif
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
181
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
182 /* copy overreaded bytes from last frame into buffer */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
183 for(; pc->overread>0; pc->overread--){
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
184 pc->buffer[pc->index++]= pc->buffer[pc->overread_index++];
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
185 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
186
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
187 pc->last_index= pc->index;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
188
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
189 /* copy into buffer end return */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
190 if(next == END_NOT_FOUND){
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
191 pc->buffer= av_fast_realloc(pc->buffer, &pc->buffer_size, (*buf_size) + pc->index + FF_INPUT_BUFFER_PADDING_SIZE);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
192
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
193 memcpy(&pc->buffer[pc->index], *buf, *buf_size);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
194 pc->index += *buf_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
195 return -1;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
196 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
197
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
198 *buf_size=
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
199 pc->overread_index= pc->index + next;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
200
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
201 /* append to buffer */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
202 if(pc->index){
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
203 pc->buffer= av_fast_realloc(pc->buffer, &pc->buffer_size, next + pc->index + FF_INPUT_BUFFER_PADDING_SIZE);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
204
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
205 memcpy(&pc->buffer[pc->index], *buf, next + FF_INPUT_BUFFER_PADDING_SIZE );
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
206 pc->index = 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
207 *buf= pc->buffer;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
208 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
209
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
210 /* store overread bytes */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
211 for(;next < 0; next++){
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
212 pc->state = (pc->state<<8) | pc->buffer[pc->last_index + next];
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
213 pc->overread++;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
214 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
215
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
216 #if 0
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
217 if(pc->overread){
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
218 printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
219 printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
220 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
221 #endif
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
222
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
223 return 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
224 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
225
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
226 static int find_start_code(const uint8_t **pbuf_ptr, const uint8_t *buf_end)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
227 {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
228 const uint8_t *buf_ptr;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
229 unsigned int state=0xFFFFFFFF, v;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
230 int val;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
231
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
232 buf_ptr = *pbuf_ptr;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
233 while (buf_ptr < buf_end) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
234 v = *buf_ptr++;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
235 if (state == 0x000001) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
236 state = ((state << 8) | v) & 0xffffff;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
237 val = state;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
238 goto found;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
239 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
240 state = ((state << 8) | v) & 0xffffff;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
241 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
242 val = -1;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
243 found:
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
244 *pbuf_ptr = buf_ptr;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
245 return val;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
246 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
247
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
248 /* XXX: merge with libavcodec ? */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
249 #define MPEG1_FRAME_RATE_BASE 1001
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
250
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
251 static const int frame_rate_tab[16] = {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
252 0,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
253 24000,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
254 24024,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
255 25025,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
256 30000,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
257 30030,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
258 50050,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
259 60000,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
260 60060,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
261 // Xing's 15fps: (9)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
262 15015,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
263 // libmpeg3's "Unofficial economy rates": (10-13)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
264 5005,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
265 10010,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
266 12012,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
267 15015,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
268 // random, just to avoid segfault !never encode these
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
269 25025,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
270 25025,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
271 };
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
272
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
273 static void mpegvideo_extract_headers(AVCodecParserContext *s,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
274 AVCodecContext *avctx,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
275 const uint8_t *buf, int buf_size)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
276 {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
277 ParseContext1 *pc = s->priv_data;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
278 const uint8_t *buf_end;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
279 int32_t start_code;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
280 int frame_rate_index, ext_type, bytes_left;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
281 int frame_rate_ext_n, frame_rate_ext_d;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
282 int top_field_first, repeat_first_field, progressive_frame;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
283 int horiz_size_ext, vert_size_ext;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
284
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
285 s->repeat_pict = 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
286 buf_end = buf + buf_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
287 while (buf < buf_end) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
288 start_code = find_start_code(&buf, buf_end);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
289 bytes_left = buf_end - buf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
290 switch(start_code) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
291 case PICTURE_START_CODE:
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
292 if (bytes_left >= 2) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
293 s->pict_type = (buf[1] >> 3) & 7;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
294 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
295 break;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
296 case SEQ_START_CODE:
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
297 if (bytes_left >= 4) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
298 pc->width = avctx->width = (buf[0] << 4) | (buf[1] >> 4);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
299 pc->height = avctx->height = ((buf[1] & 0x0f) << 8) | buf[2];
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
300 frame_rate_index = buf[3] & 0xf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
301 pc->frame_rate = avctx->frame_rate = frame_rate_tab[frame_rate_index];
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
302 avctx->frame_rate_base = MPEG1_FRAME_RATE_BASE;
1681
27a272442d6b fill codec info
bellard
parents: 1614
diff changeset
303 avctx->codec_id = CODEC_ID_MPEG1VIDEO;
27a272442d6b fill codec info
bellard
parents: 1614
diff changeset
304 avctx->sub_id = 1;
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
305 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
306 break;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
307 case EXT_START_CODE:
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
308 if (bytes_left >= 1) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
309 ext_type = (buf[0] >> 4);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
310 switch(ext_type) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
311 case 0x1: /* sequence extension */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
312 if (bytes_left >= 6) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
313 horiz_size_ext = ((buf[1] & 1) << 1) | (buf[2] >> 7);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
314 vert_size_ext = (buf[2] >> 5) & 3;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
315 frame_rate_ext_n = (buf[5] >> 5) & 3;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
316 frame_rate_ext_d = (buf[5] & 0x1f);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
317 pc->progressive_sequence = buf[1] & (1 << 3);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
318
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
319 avctx->width = pc->width | (horiz_size_ext << 12);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
320 avctx->height = pc->height | (vert_size_ext << 12);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
321 avctx->frame_rate = pc->frame_rate * (frame_rate_ext_n + 1);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
322 avctx->frame_rate_base = MPEG1_FRAME_RATE_BASE * (frame_rate_ext_d + 1);
1681
27a272442d6b fill codec info
bellard
parents: 1614
diff changeset
323 avctx->codec_id = CODEC_ID_MPEG2VIDEO;
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
324 avctx->sub_id = 2; /* forces MPEG2 */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
325 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
326 break;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
327 case 0x8: /* picture coding extension */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
328 if (bytes_left >= 5) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
329 top_field_first = buf[3] & (1 << 7);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
330 repeat_first_field = buf[3] & (1 << 1);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
331 progressive_frame = buf[4] & (1 << 7);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
332
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
333 /* check if we must repeat the frame */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
334 if (repeat_first_field) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
335 if (pc->progressive_sequence) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
336 if (top_field_first)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
337 s->repeat_pict = 4;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
338 else
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
339 s->repeat_pict = 2;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
340 } else if (progressive_frame) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
341 s->repeat_pict = 1;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
342 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
343 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
344 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
345 break;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
346 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
347 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
348 break;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
349 case -1:
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
350 goto the_end;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
351 default:
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
352 /* we stop parsing when we encounter a slice. It ensures
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
353 that this function takes a negligible amount of time */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
354 if (start_code >= SLICE_MIN_START_CODE &&
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
355 start_code <= SLICE_MAX_START_CODE)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
356 goto the_end;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
357 break;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
358 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
359 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
360 the_end: ;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
361 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
362
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
363 static int mpegvideo_parse(AVCodecParserContext *s,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
364 AVCodecContext *avctx,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
365 uint8_t **poutbuf, int *poutbuf_size,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
366 const uint8_t *buf, int buf_size)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
367 {
1988
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
368 ParseContext1 *pc1 = s->priv_data;
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
369 ParseContext *pc= &pc1->pc;
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
370 int next;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
371
1988
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
372 next= ff_mpeg1_find_frame_end(pc, buf, buf_size);
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
373
1988
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
374 if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) {
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
375 *poutbuf = NULL;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
376 *poutbuf_size = 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
377 return buf_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
378 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
379 /* we have a full frame : we just parse the first few MPEG headers
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
380 to have the full timing information. The time take by this
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
381 function should be negligible for uncorrupted streams */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
382 mpegvideo_extract_headers(s, avctx, buf, buf_size);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
383 #if 0
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
384 printf("pict_type=%d frame_rate=%0.3f repeat_pict=%d\n",
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
385 s->pict_type, (double)avctx->frame_rate / avctx->frame_rate_base, s->repeat_pict);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
386 #endif
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
387
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
388 *poutbuf = (uint8_t *)buf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
389 *poutbuf_size = buf_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
390 return next;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
391 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
392
1988
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
393 void ff_parse_close(AVCodecParserContext *s)
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
394 {
1988
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
395 ParseContext *pc = s->priv_data;
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
396
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
397 av_free(pc->buffer);
1988
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
398 }
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
399
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
400 static void parse1_close(AVCodecParserContext *s)
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
401 {
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
402 ParseContext1 *pc1 = s->priv_data;
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
403
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
404 av_free(pc1->pc.buffer);
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
405 av_free(pc1->enc);
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
406 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
407
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
408 /*************************/
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
409
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
410 /* used by parser */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
411 /* XXX: make it use less memory */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
412 static int av_mpeg4_decode_header(AVCodecParserContext *s1,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
413 AVCodecContext *avctx,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
414 const uint8_t *buf, int buf_size)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
415 {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
416 ParseContext1 *pc = s1->priv_data;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
417 MpegEncContext *s = pc->enc;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
418 GetBitContext gb1, *gb = &gb1;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
419 int ret;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
420
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
421 s->avctx = avctx;
1614
6c82ef97d3e6 also parse extradata for MPEG4
bellard
parents: 1613
diff changeset
422 s->current_picture_ptr = &s->current_picture;
6c82ef97d3e6 also parse extradata for MPEG4
bellard
parents: 1613
diff changeset
423
6c82ef97d3e6 also parse extradata for MPEG4
bellard
parents: 1613
diff changeset
424 if (avctx->extradata_size && pc->first_picture){
6c82ef97d3e6 also parse extradata for MPEG4
bellard
parents: 1613
diff changeset
425 init_get_bits(gb, avctx->extradata, avctx->extradata_size*8);
6c82ef97d3e6 also parse extradata for MPEG4
bellard
parents: 1613
diff changeset
426 ret = ff_mpeg4_decode_picture_header(s, gb);
6c82ef97d3e6 also parse extradata for MPEG4
bellard
parents: 1613
diff changeset
427 }
6c82ef97d3e6 also parse extradata for MPEG4
bellard
parents: 1613
diff changeset
428
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
429 init_get_bits(gb, buf, 8 * buf_size);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
430 ret = ff_mpeg4_decode_picture_header(s, gb);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
431 if (s->width) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
432 avctx->width = s->width;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
433 avctx->height = s->height;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
434 }
1614
6c82ef97d3e6 also parse extradata for MPEG4
bellard
parents: 1613
diff changeset
435 pc->first_picture = 0;
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
436 return ret;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
437 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
438
2024
f65d87bfdd5a some of the warning fixes by (Michael Roitzsch <mroi at users dot sourceforge dot net>)
michael
parents: 1988
diff changeset
439 static int mpeg4video_parse_init(AVCodecParserContext *s)
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
440 {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
441 ParseContext1 *pc = s->priv_data;
1614
6c82ef97d3e6 also parse extradata for MPEG4
bellard
parents: 1613
diff changeset
442
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
443 pc->enc = av_mallocz(sizeof(MpegEncContext));
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
444 if (!pc->enc)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
445 return -1;
1614
6c82ef97d3e6 also parse extradata for MPEG4
bellard
parents: 1613
diff changeset
446 pc->first_picture = 1;
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
447 return 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
448 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
449
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
450 static int mpeg4video_parse(AVCodecParserContext *s,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
451 AVCodecContext *avctx,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
452 uint8_t **poutbuf, int *poutbuf_size,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
453 const uint8_t *buf, int buf_size)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
454 {
1988
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
455 ParseContext *pc = s->priv_data;
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
456 int next;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
457
1988
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
458 next= ff_mpeg4_find_frame_end(pc, buf, buf_size);
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
459
1988
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
460 if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) {
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
461 *poutbuf = NULL;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
462 *poutbuf_size = 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
463 return buf_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
464 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
465 av_mpeg4_decode_header(s, avctx, buf, buf_size);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
466
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
467 *poutbuf = (uint8_t *)buf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
468 *poutbuf_size = buf_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
469 return next;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
470 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
471
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
472 /*************************/
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
473
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
474 typedef struct MpegAudioParseContext {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
475 uint8_t inbuf[MPA_MAX_CODED_FRAME_SIZE]; /* input buffer */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
476 uint8_t *inbuf_ptr;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
477 int frame_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
478 int free_format_frame_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
479 int free_format_next_header;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
480 } MpegAudioParseContext;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
481
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
482 #define MPA_HEADER_SIZE 4
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
483
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
484 /* header + layer + bitrate + freq + lsf/mpeg25 */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
485 #define SAME_HEADER_MASK \
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
486 (0xffe00000 | (3 << 17) | (0xf << 12) | (3 << 10) | (3 << 19))
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
487
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
488 static int mpegaudio_parse_init(AVCodecParserContext *s1)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
489 {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
490 MpegAudioParseContext *s = s1->priv_data;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
491 s->inbuf_ptr = s->inbuf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
492 return 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
493 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
494
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
495 static int mpegaudio_parse(AVCodecParserContext *s1,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
496 AVCodecContext *avctx,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
497 uint8_t **poutbuf, int *poutbuf_size,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
498 const uint8_t *buf, int buf_size)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
499 {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
500 MpegAudioParseContext *s = s1->priv_data;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
501 int len, ret;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
502 uint32_t header;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
503 const uint8_t *buf_ptr;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
504
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
505 *poutbuf = NULL;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
506 *poutbuf_size = 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
507 buf_ptr = buf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
508 while (buf_size > 0) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
509 len = s->inbuf_ptr - s->inbuf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
510 if (s->frame_size == 0) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
511 /* special case for next header for first frame in free
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
512 format case (XXX: find a simpler method) */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
513 if (s->free_format_next_header != 0) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
514 s->inbuf[0] = s->free_format_next_header >> 24;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
515 s->inbuf[1] = s->free_format_next_header >> 16;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
516 s->inbuf[2] = s->free_format_next_header >> 8;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
517 s->inbuf[3] = s->free_format_next_header;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
518 s->inbuf_ptr = s->inbuf + 4;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
519 s->free_format_next_header = 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
520 goto got_header;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
521 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
522 /* no header seen : find one. We need at least MPA_HEADER_SIZE
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
523 bytes to parse it */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
524 len = MPA_HEADER_SIZE - len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
525 if (len > buf_size)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
526 len = buf_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
527 if (len > 0) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
528 memcpy(s->inbuf_ptr, buf_ptr, len);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
529 buf_ptr += len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
530 buf_size -= len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
531 s->inbuf_ptr += len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
532 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
533 if ((s->inbuf_ptr - s->inbuf) >= MPA_HEADER_SIZE) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
534 got_header:
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
535 header = (s->inbuf[0] << 24) | (s->inbuf[1] << 16) |
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
536 (s->inbuf[2] << 8) | s->inbuf[3];
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
537
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
538 ret = mpa_decode_header(avctx, header);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
539 if (ret < 0) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
540 /* no sync found : move by one byte (inefficient, but simple!) */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
541 memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
542 s->inbuf_ptr--;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
543 dprintf("skip %x\n", header);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
544 /* reset free format frame size to give a chance
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
545 to get a new bitrate */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
546 s->free_format_frame_size = 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
547 } else {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
548 s->frame_size = ret;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
549 #if 0
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
550 /* free format: prepare to compute frame size */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
551 if (decode_header(s, header) == 1) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
552 s->frame_size = -1;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
553 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
554 #endif
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
555 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
556 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
557 } else
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
558 #if 0
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
559 if (s->frame_size == -1) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
560 /* free format : find next sync to compute frame size */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
561 len = MPA_MAX_CODED_FRAME_SIZE - len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
562 if (len > buf_size)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
563 len = buf_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
564 if (len == 0) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
565 /* frame too long: resync */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
566 s->frame_size = 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
567 memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
568 s->inbuf_ptr--;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
569 } else {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
570 uint8_t *p, *pend;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
571 uint32_t header1;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
572 int padding;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
573
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
574 memcpy(s->inbuf_ptr, buf_ptr, len);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
575 /* check for header */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
576 p = s->inbuf_ptr - 3;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
577 pend = s->inbuf_ptr + len - 4;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
578 while (p <= pend) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
579 header = (p[0] << 24) | (p[1] << 16) |
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
580 (p[2] << 8) | p[3];
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
581 header1 = (s->inbuf[0] << 24) | (s->inbuf[1] << 16) |
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
582 (s->inbuf[2] << 8) | s->inbuf[3];
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
583 /* check with high probability that we have a
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
584 valid header */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
585 if ((header & SAME_HEADER_MASK) ==
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
586 (header1 & SAME_HEADER_MASK)) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
587 /* header found: update pointers */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
588 len = (p + 4) - s->inbuf_ptr;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
589 buf_ptr += len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
590 buf_size -= len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
591 s->inbuf_ptr = p;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
592 /* compute frame size */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
593 s->free_format_next_header = header;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
594 s->free_format_frame_size = s->inbuf_ptr - s->inbuf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
595 padding = (header1 >> 9) & 1;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
596 if (s->layer == 1)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
597 s->free_format_frame_size -= padding * 4;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
598 else
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
599 s->free_format_frame_size -= padding;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
600 dprintf("free frame size=%d padding=%d\n",
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
601 s->free_format_frame_size, padding);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
602 decode_header(s, header1);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
603 goto next_data;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
604 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
605 p++;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
606 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
607 /* not found: simply increase pointers */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
608 buf_ptr += len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
609 s->inbuf_ptr += len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
610 buf_size -= len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
611 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
612 } else
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
613 #endif
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
614 if (len < s->frame_size) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
615 if (s->frame_size > MPA_MAX_CODED_FRAME_SIZE)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
616 s->frame_size = MPA_MAX_CODED_FRAME_SIZE;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
617 len = s->frame_size - len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
618 if (len > buf_size)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
619 len = buf_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
620 memcpy(s->inbuf_ptr, buf_ptr, len);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
621 buf_ptr += len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
622 s->inbuf_ptr += len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
623 buf_size -= len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
624 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
625 // next_data:
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
626 if (s->frame_size > 0 &&
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
627 (s->inbuf_ptr - s->inbuf) >= s->frame_size) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
628 *poutbuf = s->inbuf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
629 *poutbuf_size = s->inbuf_ptr - s->inbuf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
630 s->inbuf_ptr = s->inbuf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
631 s->frame_size = 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
632 break;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
633 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
634 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
635 return buf_ptr - buf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
636 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
637
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
638 #ifdef CONFIG_AC3
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
639 extern int a52_syncinfo (const uint8_t * buf, int * flags,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
640 int * sample_rate, int * bit_rate);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
641
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
642 typedef struct AC3ParseContext {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
643 uint8_t inbuf[4096]; /* input buffer */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
644 uint8_t *inbuf_ptr;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
645 int frame_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
646 int flags;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
647 } AC3ParseContext;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
648
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
649 #define AC3_HEADER_SIZE 7
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
650 #define A52_LFE 16
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
651
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
652 static int ac3_parse_init(AVCodecParserContext *s1)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
653 {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
654 AC3ParseContext *s = s1->priv_data;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
655 s->inbuf_ptr = s->inbuf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
656 return 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
657 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
658
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
659 static int ac3_parse(AVCodecParserContext *s1,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
660 AVCodecContext *avctx,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
661 uint8_t **poutbuf, int *poutbuf_size,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
662 const uint8_t *buf, int buf_size)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
663 {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
664 AC3ParseContext *s = s1->priv_data;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
665 const uint8_t *buf_ptr;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
666 int len, sample_rate, bit_rate;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
667 static const int ac3_channels[8] = {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
668 2, 1, 2, 3, 3, 4, 4, 5
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
669 };
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
670
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
671 *poutbuf = NULL;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
672 *poutbuf_size = 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
673
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
674 buf_ptr = buf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
675 while (buf_size > 0) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
676 len = s->inbuf_ptr - s->inbuf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
677 if (s->frame_size == 0) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
678 /* no header seen : find one. We need at least 7 bytes to parse it */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
679 len = AC3_HEADER_SIZE - len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
680 if (len > buf_size)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
681 len = buf_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
682 memcpy(s->inbuf_ptr, buf_ptr, len);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
683 buf_ptr += len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
684 s->inbuf_ptr += len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
685 buf_size -= len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
686 if ((s->inbuf_ptr - s->inbuf) == AC3_HEADER_SIZE) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
687 len = a52_syncinfo(s->inbuf, &s->flags, &sample_rate, &bit_rate);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
688 if (len == 0) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
689 /* no sync found : move by one byte (inefficient, but simple!) */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
690 memmove(s->inbuf, s->inbuf + 1, AC3_HEADER_SIZE - 1);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
691 s->inbuf_ptr--;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
692 } else {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
693 s->frame_size = len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
694 /* update codec info */
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
695 avctx->sample_rate = sample_rate;
1987
d9e067853051 >2 channels decoding fix
michael
parents: 1696
diff changeset
696 /* set channels,except if the user explicitly requests 1 or 2 channels, XXX/FIXME this is a bit ugly */
d9e067853051 >2 channels decoding fix
michael
parents: 1696
diff changeset
697 if(avctx->channels!=1 && avctx->channels!=2){
d9e067853051 >2 channels decoding fix
michael
parents: 1696
diff changeset
698 avctx->channels = ac3_channels[s->flags & 7];
d9e067853051 >2 channels decoding fix
michael
parents: 1696
diff changeset
699 if (s->flags & A52_LFE)
d9e067853051 >2 channels decoding fix
michael
parents: 1696
diff changeset
700 avctx->channels++;
d9e067853051 >2 channels decoding fix
michael
parents: 1696
diff changeset
701 }
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
702 avctx->bit_rate = bit_rate;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
703 avctx->frame_size = 6 * 256;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
704 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
705 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
706 } else if (len < s->frame_size) {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
707 len = s->frame_size - len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
708 if (len > buf_size)
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
709 len = buf_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
710
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
711 memcpy(s->inbuf_ptr, buf_ptr, len);
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
712 buf_ptr += len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
713 s->inbuf_ptr += len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
714 buf_size -= len;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
715 } else {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
716 *poutbuf = s->inbuf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
717 *poutbuf_size = s->frame_size;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
718 s->inbuf_ptr = s->inbuf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
719 s->frame_size = 0;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
720 break;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
721 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
722 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
723 return buf_ptr - buf;
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
724 }
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
725 #endif
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
726
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
727 AVCodecParser mpegvideo_parser = {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
728 { CODEC_ID_MPEG1VIDEO, CODEC_ID_MPEG2VIDEO },
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
729 sizeof(ParseContext1),
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
730 NULL,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
731 mpegvideo_parse,
1988
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
732 parse1_close,
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
733 };
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
734
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
735 AVCodecParser mpeg4video_parser = {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
736 { CODEC_ID_MPEG4 },
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
737 sizeof(ParseContext1),
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
738 mpeg4video_parse_init,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
739 mpeg4video_parse,
1988
b5753525f9a8 remove duplicated find_frame_end() code
michael
parents: 1987
diff changeset
740 parse1_close,
1613
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
741 };
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
742
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
743 AVCodecParser mpegaudio_parser = {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
744 { CODEC_ID_MP2, CODEC_ID_MP3 },
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
745 sizeof(MpegAudioParseContext),
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
746 mpegaudio_parse_init,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
747 mpegaudio_parse,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
748 NULL,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
749 };
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
750
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
751 #ifdef CONFIG_AC3
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
752 AVCodecParser ac3_parser = {
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
753 { CODEC_ID_AC3 },
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
754 sizeof(AC3ParseContext),
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
755 ac3_parse_init,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
756 ac3_parse,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
757 NULL,
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
758 };
0279c6c61f11 new audio/video parser API
bellard
parents:
diff changeset
759 #endif