/src/ffmpeg/libavcodec/mpeg4video_parser.c
Line | Count | Source |
1 | | /* |
2 | | * MPEG-4 video frame extraction |
3 | | * Copyright (c) 2003 Fabrice Bellard |
4 | | * Copyright (c) 2003 Michael Niedermayer |
5 | | * |
6 | | * This file is part of FFmpeg. |
7 | | * |
8 | | * FFmpeg is free software; you can redistribute it and/or |
9 | | * modify it under the terms of the GNU Lesser General Public |
10 | | * License as published by the Free Software Foundation; either |
11 | | * version 2.1 of the License, or (at your option) any later version. |
12 | | * |
13 | | * FFmpeg is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | | * Lesser General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public |
19 | | * License along with FFmpeg; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | | */ |
22 | | |
23 | | #define UNCHECKED_BITSTREAM_READER 1 |
24 | | |
25 | | #include "decode.h" |
26 | | #include "parser.h" |
27 | | #include "mpegvideo.h" |
28 | | #include "mpeg4videodec.h" |
29 | | #include "mpeg4videodefs.h" |
30 | | #include "parser_internal.h" |
31 | | |
32 | | struct Mp4vParseContext { |
33 | | ParseContext pc; |
34 | | Mpeg4DecContext dec_ctx; |
35 | | int first_picture; |
36 | | }; |
37 | | |
38 | | /** |
39 | | * Find the end of the current frame in the bitstream. |
40 | | * @return the position of the first byte of the next frame, or -1 |
41 | | */ |
42 | | static int mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) |
43 | 832k | { |
44 | 832k | int vop_found, i; |
45 | 832k | uint32_t state; |
46 | | |
47 | 832k | vop_found = pc->frame_start_found; |
48 | 832k | state = pc->state; |
49 | | |
50 | 832k | i = 0; |
51 | 832k | if (!vop_found) { |
52 | 64.0M | for (i = 0; i < buf_size; i++) { |
53 | 63.9M | state = (state << 8) | buf[i]; |
54 | 63.9M | if (state == VOP_STARTCODE) { |
55 | 724k | i++; |
56 | 724k | vop_found = 1; |
57 | 724k | break; |
58 | 724k | } |
59 | 63.9M | } |
60 | 800k | } |
61 | | |
62 | 832k | if (vop_found) { |
63 | | /* EOF considered as end of frame */ |
64 | 756k | if (buf_size == 0) |
65 | 1.69k | return 0; |
66 | 33.8M | for (; i < buf_size; i++) { |
67 | 33.7M | state = (state << 8) | buf[i]; |
68 | 33.7M | if ((state & 0xFFFFFF00) == 0x100) { |
69 | 752k | if (state == SLICE_STARTCODE || state == EXT_STARTCODE) |
70 | 29.9k | continue; |
71 | 722k | pc->frame_start_found = 0; |
72 | 722k | pc->state = -1; |
73 | 722k | return i - 3; |
74 | 752k | } |
75 | 33.7M | } |
76 | 754k | } |
77 | 108k | pc->frame_start_found = vop_found; |
78 | 108k | pc->state = state; |
79 | 108k | return END_NOT_FOUND; |
80 | 832k | } |
81 | | |
82 | | /* XXX: make it use less memory */ |
83 | | static int mpeg4_decode_header(AVCodecParserContext *s1, AVCodecContext *avctx, |
84 | | const uint8_t *buf, int buf_size) |
85 | 732k | { |
86 | 732k | struct Mp4vParseContext *pc = s1->priv_data; |
87 | 732k | Mpeg4DecContext *dec_ctx = &pc->dec_ctx; |
88 | 732k | MPVContext *const s = &dec_ctx->h.c; |
89 | 732k | GetBitContext gb1, *gb = &gb1; |
90 | 732k | int ret; |
91 | | |
92 | 732k | s->avctx = avctx; |
93 | | |
94 | 732k | if (avctx->extradata_size && pc->first_picture) { |
95 | 6.87k | init_get_bits(gb, avctx->extradata, avctx->extradata_size * 8); |
96 | 6.87k | ret = ff_mpeg4_parse_picture_header(dec_ctx, gb, 1, 1); |
97 | 6.87k | if (ret < 0) |
98 | 1.00k | av_log(avctx, AV_LOG_WARNING, "Failed to parse extradata\n"); |
99 | 6.87k | } |
100 | | |
101 | 732k | init_get_bits(gb, buf, 8 * buf_size); |
102 | 732k | ret = ff_mpeg4_parse_picture_header(dec_ctx, gb, 0, 1); |
103 | 732k | avctx->has_b_frames = !s->low_delay; |
104 | 732k | if (s->width && (!avctx->width || !avctx->height || |
105 | 633k | !avctx->coded_width || !avctx->coded_height)) { |
106 | 19.6k | ret = ff_set_dimensions(avctx, s->width, s->height); |
107 | 19.6k | if (ret < 0) |
108 | 15.9k | return ret; |
109 | 19.6k | } |
110 | 716k | if((s1->flags & PARSER_FLAG_USE_CODEC_TS) && s->avctx->framerate.num>0 && ret>=0){ |
111 | 167k | av_assert1(s1->pts == AV_NOPTS_VALUE); |
112 | 167k | av_assert1(s1->dts == AV_NOPTS_VALUE); |
113 | | |
114 | 167k | s1->pts = av_rescale_q(s->time, (AVRational){1, s->avctx->framerate.num}, (AVRational){1, 1200000}); |
115 | 167k | } |
116 | | |
117 | 716k | s1->pict_type = s->pict_type; |
118 | 716k | pc->first_picture = 0; |
119 | 716k | return ret; |
120 | 732k | } |
121 | | |
122 | | static av_cold int mpeg4video_parse_init(AVCodecParserContext *s) |
123 | 5.54k | { |
124 | 5.54k | struct Mp4vParseContext *pc = s->priv_data; |
125 | | |
126 | 5.54k | pc->first_picture = 1; |
127 | 5.54k | pc->dec_ctx.quant_precision = 5; |
128 | 5.54k | pc->dec_ctx.h.c.slice_context_count = 1; |
129 | 5.54k | pc->dec_ctx.showed_packed_warning = 1; |
130 | 5.54k | return 0; |
131 | 5.54k | } |
132 | | |
133 | | static int mpeg4video_parse(AVCodecParserContext *s, |
134 | | AVCodecContext *avctx, |
135 | | const uint8_t **poutbuf, int *poutbuf_size, |
136 | | const uint8_t *buf, int buf_size) |
137 | 837k | { |
138 | 837k | ParseContext *pc = s->priv_data; |
139 | 837k | int next; |
140 | | |
141 | 837k | if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { |
142 | 4.96k | next = buf_size; |
143 | 832k | } else { |
144 | 832k | next = mpeg4_find_frame_end(pc, buf, buf_size); |
145 | | |
146 | 832k | if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { |
147 | 105k | *poutbuf = NULL; |
148 | 105k | *poutbuf_size = 0; |
149 | 105k | return buf_size; |
150 | 105k | } |
151 | 832k | } |
152 | 732k | mpeg4_decode_header(s, avctx, buf, buf_size); |
153 | | |
154 | 732k | *poutbuf = buf; |
155 | 732k | *poutbuf_size = buf_size; |
156 | 732k | return next; |
157 | 837k | } |
158 | | |
159 | | const FFCodecParser ff_mpeg4video_parser = { |
160 | | PARSER_CODEC_LIST(AV_CODEC_ID_MPEG4), |
161 | | .priv_data_size = sizeof(struct Mp4vParseContext), |
162 | | .init = mpeg4video_parse_init, |
163 | | .parse = mpeg4video_parse, |
164 | | .close = ff_parse_close, |
165 | | }; |