/src/ffmpeg/libavcodec/mpegutils.c
Line | Count | Source |
1 | | /* |
2 | | * Mpeg video formats-related defines and utility functions |
3 | | * |
4 | | * This file is part of FFmpeg. |
5 | | * |
6 | | * FFmpeg is free software; you can redistribute it and/or |
7 | | * modify it under the terms of the GNU Lesser General Public |
8 | | * License as published by the Free Software Foundation; either |
9 | | * version 2.1 of the License, or (at your option) any later version. |
10 | | * |
11 | | * FFmpeg is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | * Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with FFmpeg; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | */ |
20 | | |
21 | | #include <stdint.h> |
22 | | |
23 | | #include "libavutil/bprint.h" |
24 | | #include "libavutil/common.h" |
25 | | #include "libavutil/emms.h" |
26 | | #include "libavutil/frame.h" |
27 | | #include "libavutil/mem.h" |
28 | | #include "libavutil/pixdesc.h" |
29 | | #include "libavutil/motion_vector.h" |
30 | | #include "libavutil/avassert.h" |
31 | | |
32 | | #include "avcodec.h" |
33 | | #include "mpegutils.h" |
34 | | |
35 | | static int add_mb(AVMotionVector *mb, uint32_t mb_type, |
36 | | int dst_x, int dst_y, |
37 | | int motion_x, int motion_y, int motion_scale, |
38 | | int direction) |
39 | 53.2M | { |
40 | 53.2M | mb->w = IS_8X8(mb_type) || IS_8X16(mb_type) ? 8 : 16; |
41 | 53.2M | mb->h = IS_8X8(mb_type) || IS_16X8(mb_type) ? 8 : 16; |
42 | 53.2M | mb->motion_x = motion_x; |
43 | 53.2M | mb->motion_y = motion_y; |
44 | 53.2M | mb->motion_scale = motion_scale; |
45 | 53.2M | mb->dst_x = dst_x; |
46 | 53.2M | mb->dst_y = dst_y; |
47 | 53.2M | mb->src_x = dst_x + motion_x / motion_scale; |
48 | 53.2M | mb->src_y = dst_y + motion_y / motion_scale; |
49 | 53.2M | mb->source = direction ? 1 : -1; |
50 | 53.2M | mb->flags = 0; // XXX: does mb_type contain extra information that could be exported here? |
51 | 53.2M | return 1; |
52 | 53.2M | } |
53 | | |
54 | | void ff_draw_horiz_band(AVCodecContext *avctx, |
55 | | const AVFrame *cur, const AVFrame *last, |
56 | | int y, int h, int picture_structure, |
57 | | int first_field, int low_delay) |
58 | 6.52M | { |
59 | 6.52M | const int field_pic = picture_structure != PICT_FRAME; |
60 | 6.52M | const AVPixFmtDescriptor *desc; |
61 | 6.52M | const AVFrame *src; |
62 | 6.52M | int offset[AV_NUM_DATA_POINTERS]; |
63 | | |
64 | 6.52M | if (!avctx->draw_horiz_band) |
65 | 6.52M | return; |
66 | | |
67 | 0 | if (field_pic) { |
68 | 0 | h <<= 1; |
69 | 0 | y <<= 1; |
70 | 0 | } |
71 | |
|
72 | 0 | h = FFMIN(h, avctx->height - y); |
73 | |
|
74 | 0 | if (field_pic && first_field && |
75 | 0 | !(avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD)) |
76 | 0 | return; |
77 | | |
78 | 0 | if (cur->pict_type == AV_PICTURE_TYPE_B || low_delay || |
79 | 0 | (avctx->slice_flags & SLICE_FLAG_CODED_ORDER)) |
80 | 0 | src = cur; |
81 | 0 | else if (last) |
82 | 0 | src = last; |
83 | 0 | else |
84 | 0 | return; |
85 | | |
86 | 0 | desc = av_pix_fmt_desc_get(avctx->pix_fmt); |
87 | |
|
88 | 0 | offset[0] = y * src->linesize[0]; |
89 | 0 | offset[1] = |
90 | 0 | offset[2] = (y >> desc->log2_chroma_h) * src->linesize[1]; |
91 | 0 | for (int i = 3; i < AV_NUM_DATA_POINTERS; i++) |
92 | 0 | offset[i] = 0; |
93 | |
|
94 | 0 | emms_c(); |
95 | |
|
96 | 0 | avctx->draw_horiz_band(avctx, src, offset, |
97 | 0 | y, picture_structure, h); |
98 | 0 | } |
99 | | |
100 | 353M | #define HAS_MV_EXT(mb_type, flags, dir) ((mb_type) & flags[(dir)]) |
101 | | |
102 | | static char get_type_mv_char(int mb_type, const int mb_type_mv_flags[2]) |
103 | 150M | { |
104 | | // Type & MV direction |
105 | 150M | if (IS_PCM(mb_type)) |
106 | 95 | return 'P'; |
107 | 150M | else if (IS_ACPRED(mb_type)) |
108 | 6.72k | return 'A'; |
109 | 150M | else if (IS_INTRA4x4(mb_type)) |
110 | 29.7M | return 'i'; |
111 | 120M | else if (IS_INTRA16x16(mb_type)) |
112 | 23.5k | return 'I'; |
113 | 120M | else if (IS_DIRECT(mb_type) && IS_SKIP(mb_type)) |
114 | 99.2k | return 'd'; |
115 | 120M | else if (IS_DIRECT(mb_type)) |
116 | 34.3k | return 'D'; |
117 | 120M | else if (IS_GMC(mb_type) && IS_SKIP(mb_type)) |
118 | 10.3k | return 'g'; |
119 | 120M | else if (IS_GMC(mb_type)) |
120 | 1.50k | return 'G'; |
121 | 120M | else if (IS_SKIP(mb_type)) |
122 | 3.79M | return 'S'; |
123 | 116M | else if (!HAS_MV_EXT(mb_type, 1, mb_type_mv_flags)) |
124 | 116M | return '>'; |
125 | 112k | else if (!HAS_MV_EXT(mb_type, 0, mb_type_mv_flags)) |
126 | 68.1k | return '<'; |
127 | 43.9k | else { |
128 | 43.9k | av_assert2(HAS_MV_EXT(mb_type, 0, mb_type_mv_flags) && HAS_MV_EXT(mb_type, 1, mb_type_mv_flags)); |
129 | 43.9k | return 'X'; |
130 | 43.9k | } |
131 | 150M | } |
132 | | |
133 | | static char get_segmentation_char(int mb_type) |
134 | 150M | { |
135 | 150M | if (IS_8X8(mb_type)) |
136 | 65.2k | return '+'; |
137 | 150M | else if (IS_16X8(mb_type)) |
138 | 27.2k | return '-'; |
139 | 150M | else if (IS_8X16(mb_type)) |
140 | 14.5k | return '|'; |
141 | 150M | else if (IS_INTRA(mb_type) || IS_16X16(mb_type)) |
142 | 95.5M | return ' '; |
143 | | |
144 | 54.8M | return '?'; |
145 | 150M | } |
146 | | |
147 | | static char get_interlacement_char(int mb_type) |
148 | 150M | { |
149 | 150M | if (IS_INTERLACED(mb_type)) |
150 | 65.5k | return '='; |
151 | 150M | else |
152 | 150M | return ' '; |
153 | 150M | } |
154 | | |
155 | | void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, |
156 | | const uint32_t *mbtype_table, |
157 | | const int8_t *qscale_table, int16_t (*const motion_val[2])[2], |
158 | | int mb_width, int mb_height, int mb_stride, int quarter_sample) |
159 | 2.87M | { |
160 | 2.87M | const int is_h264 = avctx->codec_id == AV_CODEC_ID_H264; |
161 | 2.87M | const int mb_type_mv_flags[2] = { is_h264 ? MB_TYPE_L0 : MB_TYPE_FORWARD_MV, |
162 | 2.87M | is_h264 ? MB_TYPE_L1 : MB_TYPE_BACKWARD_MV }; |
163 | | |
164 | 2.87M | if ((avctx->export_side_data & AV_CODEC_EXPORT_DATA_MVS) && mbtype_table && motion_val[0]) { |
165 | 343k | const int shift = 1 + quarter_sample; |
166 | 343k | const int scale = 1 << shift; |
167 | 343k | const int mv_sample_log2 = is_h264 ? 2 : 1; |
168 | 343k | const int mv_stride = (mb_width << mv_sample_log2) + !is_h264; |
169 | 343k | int mb_x, mb_y, mbcount = 0; |
170 | | |
171 | | /* size is width * height * 2 * 4 where 2 is for directions and 4 is |
172 | | * for the maximum number of MB (4 MB in case of IS_8x8) */ |
173 | 343k | AVMotionVector *mvs = av_malloc_array(mb_width * mb_height, 2 * 4 * sizeof(AVMotionVector)); |
174 | 343k | if (!mvs) |
175 | 0 | return; |
176 | | |
177 | 16.5M | for (mb_y = 0; mb_y < mb_height; mb_y++) { |
178 | 134M | for (mb_x = 0; mb_x < mb_width; mb_x++) { |
179 | 118M | int i, direction, mb_type = mbtype_table[mb_x + mb_y * mb_stride]; |
180 | 354M | for (direction = 0; direction < 2; direction++) { |
181 | 236M | if (!HAS_MV_EXT(mb_type, direction, mb_type_mv_flags)) |
182 | 189M | continue; |
183 | 47.1M | if (IS_8X8(mb_type)) { |
184 | 8.57M | for (i = 0; i < 4; i++) { |
185 | 6.85M | int sx = mb_x * 16 + 4 + 8 * (i & 1); |
186 | 6.85M | int sy = mb_y * 16 + 4 + 8 * (i >> 1); |
187 | 6.85M | int xy = (mb_x * 2 + (i & 1) + |
188 | 6.85M | (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1); |
189 | 6.85M | int mx = motion_val[direction][xy][0]; |
190 | 6.85M | int my = motion_val[direction][xy][1]; |
191 | 6.85M | mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction); |
192 | 6.85M | } |
193 | 45.4M | } else if (IS_16X8(mb_type)) { |
194 | 1.97M | for (i = 0; i < 2; i++) { |
195 | 1.31M | int sx = mb_x * 16 + 8; |
196 | 1.31M | int sy = mb_y * 16 + 4 + 8 * i; |
197 | 1.31M | int xy = (mb_x * 2 + (mb_y * 2 + i) * mv_stride) << (mv_sample_log2 - 1); |
198 | 1.31M | int mx = motion_val[direction][xy][0]; |
199 | 1.31M | int my = motion_val[direction][xy][1]; |
200 | | |
201 | 1.31M | if (IS_INTERLACED(mb_type)) |
202 | 1.01M | my *= 2; |
203 | | |
204 | 1.31M | mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction); |
205 | 1.31M | } |
206 | 44.7M | } else if (IS_8X16(mb_type)) { |
207 | 737k | for (i = 0; i < 2; i++) { |
208 | 491k | int sx = mb_x * 16 + 4 + 8 * i; |
209 | 491k | int sy = mb_y * 16 + 8; |
210 | 491k | int xy = (mb_x * 2 + i + mb_y * 2 * mv_stride) << (mv_sample_log2 - 1); |
211 | 491k | int mx = motion_val[direction][xy][0]; |
212 | 491k | int my = motion_val[direction][xy][1]; |
213 | | |
214 | 491k | if (IS_INTERLACED(mb_type)) |
215 | 226k | my *= 2; |
216 | | |
217 | 491k | mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction); |
218 | 491k | } |
219 | 44.5M | } else { |
220 | 44.5M | int sx = mb_x * 16 + 8; |
221 | 44.5M | int sy = mb_y * 16 + 8; |
222 | 44.5M | int xy = (mb_x + mb_y * mv_stride) << mv_sample_log2; |
223 | 44.5M | int mx = motion_val[direction][xy][0]; |
224 | 44.5M | int my = motion_val[direction][xy][1]; |
225 | 44.5M | mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction); |
226 | 44.5M | } |
227 | 47.1M | } |
228 | 118M | } |
229 | 16.2M | } |
230 | | |
231 | 343k | if (mbcount) { |
232 | 201k | AVFrameSideData *sd; |
233 | | |
234 | 201k | av_log(avctx, AV_LOG_DEBUG, "Adding %d MVs info to frame %"PRId64"\n", mbcount, avctx->frame_num); |
235 | 201k | sd = av_frame_new_side_data(pict, AV_FRAME_DATA_MOTION_VECTORS, mbcount * sizeof(AVMotionVector)); |
236 | 201k | if (!sd) { |
237 | 0 | av_freep(&mvs); |
238 | 0 | return; |
239 | 0 | } |
240 | 201k | memcpy(sd->data, mvs, mbcount * sizeof(AVMotionVector)); |
241 | 201k | } |
242 | | |
243 | 343k | av_freep(&mvs); |
244 | 343k | } |
245 | | |
246 | | /* TODO: export all the following to make them accessible for users (and filters) */ |
247 | 2.87M | if (avctx->hwaccel || !mbtype_table) |
248 | 0 | return; |
249 | | |
250 | | |
251 | 2.87M | if (avctx->debug & (FF_DEBUG_QP | FF_DEBUG_MB_TYPE)) { |
252 | 180k | int x,y; |
253 | 180k | AVBPrint buf; |
254 | 180k | int n; |
255 | 180k | int margin_left; |
256 | 180k | int x_step; |
257 | | |
258 | 180k | av_log(avctx, AV_LOG_DEBUG, "New frame, type: %c\n", |
259 | 180k | av_get_picture_type_char(pict->pict_type)); |
260 | | |
261 | 180k | margin_left = 2; |
262 | 180k | n = mb_width << 4; |
263 | 489k | while ((n /= 10)) |
264 | 309k | margin_left++; |
265 | | |
266 | 180k | av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED); |
267 | 180k | av_bprint_chars(&buf, ' ', margin_left); |
268 | | |
269 | 180k | n = 0; |
270 | 180k | if (avctx->debug & FF_DEBUG_QP) |
271 | 118k | n += 2; |
272 | 180k | if (avctx->debug & FF_DEBUG_MB_TYPE) |
273 | 127k | n += 3; |
274 | 180k | x_step = (mb_width * 16 > 999) ? 8 : 4; |
275 | 2.84M | for (x = 0; x < mb_width; x += x_step) |
276 | 2.66M | av_bprintf(&buf, "%-*d", n * x_step, x << 4); |
277 | | |
278 | 180k | av_log(avctx, AV_LOG_DEBUG, "%s\n", buf.str); |
279 | | |
280 | 29.9M | for (y = 0; y < mb_height; y++) { |
281 | 29.7M | av_bprint_clear(&buf); |
282 | 246M | for (x = 0; x < mb_width; x++) { |
283 | 216M | if (x == 0) |
284 | 29.7M | av_bprintf(&buf, "%*d ", margin_left - 1, y << 4); |
285 | 216M | if (avctx->debug & FF_DEBUG_QP) { |
286 | 156M | av_bprintf(&buf, "%2d", qscale_table[x + y * mb_stride]); |
287 | 156M | } |
288 | 216M | if (avctx->debug & FF_DEBUG_MB_TYPE) { |
289 | 150M | int mb_type = mbtype_table[x + y * mb_stride]; |
290 | | |
291 | 150M | av_bprintf(&buf, "%c%c%c", |
292 | 150M | get_type_mv_char(mb_type, mb_type_mv_flags), |
293 | 150M | get_segmentation_char(mb_type), |
294 | 150M | get_interlacement_char(mb_type)); |
295 | 150M | } |
296 | 216M | } |
297 | | |
298 | 29.7M | av_log(avctx, AV_LOG_DEBUG, "%s\n", buf.str); |
299 | 29.7M | } |
300 | | av_bprint_finalize(&buf, NULL); |
301 | 180k | } |
302 | 2.87M | } |