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