/src/ffmpeg/libavcodec/cavs_parser.c
Line | Count | Source |
1 | | /* |
2 | | * Chinese AVS video (AVS1-P2, JiZhun profile) parser. |
3 | | * Copyright (c) 2006 Stefan Gehrer <stefan.gehrer@gmx.de> |
4 | | * |
5 | | * This file is part of FFmpeg. |
6 | | * |
7 | | * FFmpeg is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * FFmpeg is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with FFmpeg; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | /** |
23 | | * @file |
24 | | * Chinese AVS video (AVS1-P2, JiZhun profile) parser |
25 | | * @author Stefan Gehrer <stefan.gehrer@gmx.de> |
26 | | */ |
27 | | |
28 | | #include "parser.h" |
29 | | #include "cavs.h" |
30 | | #include "get_bits.h" |
31 | | #include "mpeg12data.h" |
32 | | #include "parser_internal.h" |
33 | | #include "startcode.h" |
34 | | |
35 | | |
36 | | /** |
37 | | * Find the end of the current frame in the bitstream. |
38 | | * @return the position of the first byte of the next frame, or -1 |
39 | | */ |
40 | | static int cavs_find_frame_end(ParseContext *pc, const uint8_t *buf, |
41 | 678k | int buf_size) { |
42 | 678k | int pic_found, i; |
43 | 678k | uint32_t state; |
44 | | |
45 | 678k | pic_found= pc->frame_start_found; |
46 | 678k | state= pc->state; |
47 | | |
48 | 678k | i=0; |
49 | 678k | if(!pic_found){ |
50 | 18.4M | for(i=0; i<buf_size; i++){ |
51 | 18.4M | state= (state<<8) | buf[i]; |
52 | 18.4M | if(state == PIC_I_START_CODE || state == PIC_PB_START_CODE){ |
53 | 654k | i++; |
54 | 654k | pic_found=1; |
55 | 654k | break; |
56 | 654k | } |
57 | 18.4M | } |
58 | 665k | } |
59 | | |
60 | 678k | if(pic_found){ |
61 | | /* EOF considered as end of frame */ |
62 | 667k | if (buf_size == 0) |
63 | 224 | return 0; |
64 | 12.0M | for(; i<buf_size; i++){ |
65 | 12.0M | state= (state<<8) | buf[i]; |
66 | 12.0M | if (state == PIC_I_START_CODE || state == PIC_PB_START_CODE || |
67 | 11.3M | state == CAVS_START_CODE) { |
68 | 653k | pc->frame_start_found=0; |
69 | 653k | pc->state=-1; |
70 | 653k | return i-3; |
71 | 653k | } |
72 | 12.0M | } |
73 | 667k | } |
74 | 24.8k | pc->frame_start_found= pic_found; |
75 | 24.8k | pc->state= state; |
76 | 24.8k | return END_NOT_FOUND; |
77 | 678k | } |
78 | | |
79 | | static int parse_seq_header(AVCodecParserContext *s, AVCodecContext *avctx, |
80 | | GetBitContext *gb) |
81 | 20.0k | { |
82 | 20.0k | int frame_rate_code; |
83 | 20.0k | int width, height; |
84 | 20.0k | int mb_width, mb_height; |
85 | | |
86 | 20.0k | skip_bits(gb, 8); // profile |
87 | 20.0k | skip_bits(gb, 8); // level |
88 | 20.0k | skip_bits1(gb); // progressive sequence |
89 | | |
90 | 20.0k | width = get_bits(gb, 14); |
91 | 20.0k | height = get_bits(gb, 14); |
92 | 20.0k | if (width <= 0 || height <= 0) { |
93 | 4.18k | av_log(avctx, AV_LOG_ERROR, "Dimensions invalid\n"); |
94 | 4.18k | return AVERROR_INVALIDDATA; |
95 | 4.18k | } |
96 | 15.9k | mb_width = (width + 15) >> 4; |
97 | 15.9k | mb_height = (height + 15) >> 4; |
98 | | |
99 | 15.9k | skip_bits(gb, 2); // chroma format |
100 | 15.9k | skip_bits(gb, 3); // sample_precision |
101 | 15.9k | skip_bits(gb, 4); // aspect_ratio |
102 | 15.9k | frame_rate_code = get_bits(gb, 4); |
103 | 15.9k | if (frame_rate_code == 0 || frame_rate_code > 13) { |
104 | 3.86k | av_log(avctx, AV_LOG_WARNING, |
105 | 3.86k | "frame_rate_code %d is invalid\n", frame_rate_code); |
106 | 3.86k | frame_rate_code = 1; |
107 | 3.86k | } |
108 | | |
109 | 15.9k | skip_bits(gb, 18); // bit_rate_lower |
110 | 15.9k | skip_bits1(gb); // marker_bit |
111 | 15.9k | skip_bits(gb, 12); // bit_rate_upper |
112 | 15.9k | skip_bits1(gb); // low_delay |
113 | | |
114 | 15.9k | s->width = width; |
115 | 15.9k | s->height = height; |
116 | 15.9k | s->coded_width = 16 * mb_width; |
117 | 15.9k | s->coded_height = 16 * mb_height; |
118 | 15.9k | avctx->framerate = ff_mpeg12_frame_rate_tab[frame_rate_code]; |
119 | | |
120 | 15.9k | return 0; |
121 | 20.0k | } |
122 | | |
123 | | static int cavs_parse_frame(AVCodecParserContext *s, AVCodecContext *avctx, |
124 | | const uint8_t *buf, int buf_size) |
125 | 654k | { |
126 | 654k | GetBitContext gb; |
127 | 654k | const uint8_t *buf_end; |
128 | 654k | const uint8_t *buf_ptr; |
129 | 654k | uint32_t stc = -1; |
130 | | |
131 | 654k | s->key_frame = 0; |
132 | 654k | s->pict_type = AV_PICTURE_TYPE_NONE; |
133 | | |
134 | 654k | if (buf_size == 0) |
135 | 162 | return 0; |
136 | | |
137 | 653k | buf_ptr = buf; |
138 | 653k | buf_end = buf + buf_size; |
139 | 915k | for (;;) { |
140 | 915k | buf_ptr = avpriv_find_start_code(buf_ptr, buf_end, &stc); |
141 | 915k | if ((stc & 0xFFFFFE00) || buf_ptr == buf_end) |
142 | 653k | return 0; |
143 | 261k | switch (stc) { |
144 | 20.0k | case CAVS_START_CODE: |
145 | 20.0k | if (init_get_bits8(&gb, buf_ptr, buf_end - buf_ptr) < 0) |
146 | 0 | return 0; |
147 | 20.0k | parse_seq_header(s, avctx, &gb); |
148 | 20.0k | break; |
149 | 76.0k | case PIC_I_START_CODE: |
150 | 76.0k | s->key_frame = 1; |
151 | 76.0k | s->pict_type = AV_PICTURE_TYPE_I; |
152 | 76.0k | break; |
153 | 165k | default: |
154 | 165k | break; |
155 | 261k | } |
156 | 261k | } |
157 | 653k | } |
158 | | |
159 | | static int cavsvideo_parse(AVCodecParserContext *s, |
160 | | AVCodecContext *avctx, |
161 | | const uint8_t **poutbuf, int *poutbuf_size, |
162 | | const uint8_t *buf, int buf_size) |
163 | 678k | { |
164 | 678k | ParseContext *pc = s->priv_data; |
165 | 678k | int next; |
166 | | |
167 | 678k | if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ |
168 | 0 | next= buf_size; |
169 | 678k | }else{ |
170 | 678k | next= cavs_find_frame_end(pc, buf, buf_size); |
171 | | |
172 | 678k | if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { |
173 | 24.7k | *poutbuf = NULL; |
174 | 24.7k | *poutbuf_size = 0; |
175 | 24.7k | return buf_size; |
176 | 24.7k | } |
177 | 678k | } |
178 | | |
179 | 654k | cavs_parse_frame(s, avctx, buf, buf_size); |
180 | | |
181 | 654k | *poutbuf = buf; |
182 | 654k | *poutbuf_size = buf_size; |
183 | 654k | return next; |
184 | 678k | } |
185 | | |
186 | | const FFCodecParser ff_cavsvideo_parser = { |
187 | | PARSER_CODEC_LIST(AV_CODEC_ID_CAVS), |
188 | | .priv_data_size = sizeof(ParseContext), |
189 | | .parse = cavsvideo_parse, |
190 | | .close = ff_parse_close, |
191 | | }; |