1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Android MediaCodec software buffer copy functions
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16cabdff1aSopenharmony_ci * Lesser General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21cabdff1aSopenharmony_ci */
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci#include <string.h>
24cabdff1aSopenharmony_ci#include <sys/types.h>
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_ci#include "libavutil/frame.h"
27cabdff1aSopenharmony_ci#include "libavutil/mem.h"
28cabdff1aSopenharmony_ci
29cabdff1aSopenharmony_ci#include "avcodec.h"
30cabdff1aSopenharmony_ci#include "mediacodec_wrapper.h"
31cabdff1aSopenharmony_ci#include "mediacodec_sw_buffer.h"
32cabdff1aSopenharmony_ci#include "mediacodecdec_common.h"
33cabdff1aSopenharmony_ci
34cabdff1aSopenharmony_ci#define QCOM_TILE_WIDTH 64
35cabdff1aSopenharmony_ci#define QCOM_TILE_HEIGHT 32
36cabdff1aSopenharmony_ci#define QCOM_TILE_SIZE (QCOM_TILE_WIDTH * QCOM_TILE_HEIGHT)
37cabdff1aSopenharmony_ci#define QCOM_TILE_GROUP_SIZE (4 * QCOM_TILE_SIZE)
38cabdff1aSopenharmony_ci
39cabdff1aSopenharmony_ci/**
40cabdff1aSopenharmony_ci * The code handling the various YUV color formats is taken from the
41cabdff1aSopenharmony_ci * GStreamer project.
42cabdff1aSopenharmony_ci *
43cabdff1aSopenharmony_ci * Gstreamer reference:
44cabdff1aSopenharmony_ci * https://cgit.freedesktop.org/gstreamer/gst-plugins-bad/tree/sys/androidmedia/
45cabdff1aSopenharmony_ci *
46cabdff1aSopenharmony_ci * Copyright (C) 2012, Collabora Ltd.
47cabdff1aSopenharmony_ci *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
48cabdff1aSopenharmony_ci *
49cabdff1aSopenharmony_ci * Copyright (C) 2012, Rafaël Carré <funman@videolanorg>
50cabdff1aSopenharmony_ci *
51cabdff1aSopenharmony_ci * Copyright (C) 2015, Sebastian Dröge <sebastian@centricular.com>
52cabdff1aSopenharmony_ci *
53cabdff1aSopenharmony_ci * Copyright (C) 2014-2015, Collabora Ltd.
54cabdff1aSopenharmony_ci *   Author: Matthieu Bouron <matthieu.bouron@gcollabora.com>
55cabdff1aSopenharmony_ci *
56cabdff1aSopenharmony_ci * Copyright (C) 2015, Edward Hervey
57cabdff1aSopenharmony_ci *   Author: Edward Hervey <bilboed@gmail.com>
58cabdff1aSopenharmony_ci *
59cabdff1aSopenharmony_ci * Copyright (C) 2015, Matthew Waters <matthew@centricular.com>
60cabdff1aSopenharmony_ci *
61cabdff1aSopenharmony_ci * This library is free software; you can redistribute it and/or
62cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
63cabdff1aSopenharmony_ci * License as published by the Free Software Foundation
64cabdff1aSopenharmony_ci * version 2.1 of the License.
65cabdff1aSopenharmony_ci *
66cabdff1aSopenharmony_ci * This library is distributed in the hope that it will be useful,
67cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
68cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
69cabdff1aSopenharmony_ci * Lesser General Public License for more details.
70cabdff1aSopenharmony_ci *
71cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
72cabdff1aSopenharmony_ci * License along with this library; if not, write to the Free Software
73cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
74cabdff1aSopenharmony_ci *
75cabdff1aSopenharmony_ci */
76cabdff1aSopenharmony_civoid ff_mediacodec_sw_buffer_copy_yuv420_planar(AVCodecContext *avctx,
77cabdff1aSopenharmony_ci                                                MediaCodecDecContext *s,
78cabdff1aSopenharmony_ci                                                uint8_t *data,
79cabdff1aSopenharmony_ci                                                size_t size,
80cabdff1aSopenharmony_ci                                                FFAMediaCodecBufferInfo *info,
81cabdff1aSopenharmony_ci                                                AVFrame *frame)
82cabdff1aSopenharmony_ci{
83cabdff1aSopenharmony_ci    int i;
84cabdff1aSopenharmony_ci    uint8_t *src = NULL;
85cabdff1aSopenharmony_ci
86cabdff1aSopenharmony_ci    for (i = 0; i < 3; i++) {
87cabdff1aSopenharmony_ci        int stride = s->stride;
88cabdff1aSopenharmony_ci        int height;
89cabdff1aSopenharmony_ci
90cabdff1aSopenharmony_ci        src = data + info->offset;
91cabdff1aSopenharmony_ci        if (i == 0) {
92cabdff1aSopenharmony_ci            height = avctx->height;
93cabdff1aSopenharmony_ci
94cabdff1aSopenharmony_ci            src += s->crop_top * s->stride;
95cabdff1aSopenharmony_ci            src += s->crop_left;
96cabdff1aSopenharmony_ci        } else {
97cabdff1aSopenharmony_ci            height = avctx->height / 2;
98cabdff1aSopenharmony_ci            stride = (s->stride + 1) / 2;
99cabdff1aSopenharmony_ci
100cabdff1aSopenharmony_ci            src += s->slice_height * s->stride;
101cabdff1aSopenharmony_ci
102cabdff1aSopenharmony_ci            if (i == 2) {
103cabdff1aSopenharmony_ci                src += ((s->slice_height + 1) / 2) * stride;
104cabdff1aSopenharmony_ci            }
105cabdff1aSopenharmony_ci
106cabdff1aSopenharmony_ci            src += s->crop_top * stride;
107cabdff1aSopenharmony_ci            src += (s->crop_left / 2);
108cabdff1aSopenharmony_ci        }
109cabdff1aSopenharmony_ci
110cabdff1aSopenharmony_ci        if (frame->linesize[i] == stride) {
111cabdff1aSopenharmony_ci            memcpy(frame->data[i], src, height * stride);
112cabdff1aSopenharmony_ci        } else {
113cabdff1aSopenharmony_ci            int j, width;
114cabdff1aSopenharmony_ci            uint8_t *dst = frame->data[i];
115cabdff1aSopenharmony_ci
116cabdff1aSopenharmony_ci            if (i == 0) {
117cabdff1aSopenharmony_ci                width = avctx->width;
118cabdff1aSopenharmony_ci            } else if (i >= 1) {
119cabdff1aSopenharmony_ci                width = FFMIN(frame->linesize[i], FFALIGN(avctx->width, 2) / 2);
120cabdff1aSopenharmony_ci            }
121cabdff1aSopenharmony_ci
122cabdff1aSopenharmony_ci            for (j = 0; j < height; j++) {
123cabdff1aSopenharmony_ci                memcpy(dst, src, width);
124cabdff1aSopenharmony_ci                src += stride;
125cabdff1aSopenharmony_ci                dst += frame->linesize[i];
126cabdff1aSopenharmony_ci            }
127cabdff1aSopenharmony_ci        }
128cabdff1aSopenharmony_ci    }
129cabdff1aSopenharmony_ci}
130cabdff1aSopenharmony_ci
131cabdff1aSopenharmony_civoid ff_mediacodec_sw_buffer_copy_yuv420_semi_planar(AVCodecContext *avctx,
132cabdff1aSopenharmony_ci                                                     MediaCodecDecContext *s,
133cabdff1aSopenharmony_ci                                                     uint8_t *data,
134cabdff1aSopenharmony_ci                                                     size_t size,
135cabdff1aSopenharmony_ci                                                     FFAMediaCodecBufferInfo *info,
136cabdff1aSopenharmony_ci                                                     AVFrame *frame)
137cabdff1aSopenharmony_ci{
138cabdff1aSopenharmony_ci    int i;
139cabdff1aSopenharmony_ci    uint8_t *src = NULL;
140cabdff1aSopenharmony_ci
141cabdff1aSopenharmony_ci    for (i = 0; i < 2; i++) {
142cabdff1aSopenharmony_ci        int height;
143cabdff1aSopenharmony_ci
144cabdff1aSopenharmony_ci        src = data + info->offset;
145cabdff1aSopenharmony_ci        if (i == 0) {
146cabdff1aSopenharmony_ci            height = avctx->height;
147cabdff1aSopenharmony_ci
148cabdff1aSopenharmony_ci            src += s->crop_top * s->stride;
149cabdff1aSopenharmony_ci            src += s->crop_left;
150cabdff1aSopenharmony_ci        } else if (i == 1) {
151cabdff1aSopenharmony_ci            height = avctx->height / 2;
152cabdff1aSopenharmony_ci
153cabdff1aSopenharmony_ci            src += s->slice_height * s->stride;
154cabdff1aSopenharmony_ci            src += s->crop_top * s->stride;
155cabdff1aSopenharmony_ci            src += s->crop_left;
156cabdff1aSopenharmony_ci        }
157cabdff1aSopenharmony_ci
158cabdff1aSopenharmony_ci        if (frame->linesize[i] == s->stride) {
159cabdff1aSopenharmony_ci            memcpy(frame->data[i], src, height * s->stride);
160cabdff1aSopenharmony_ci        } else {
161cabdff1aSopenharmony_ci            int j, width;
162cabdff1aSopenharmony_ci            uint8_t *dst = frame->data[i];
163cabdff1aSopenharmony_ci
164cabdff1aSopenharmony_ci            if (i == 0) {
165cabdff1aSopenharmony_ci                width = avctx->width;
166cabdff1aSopenharmony_ci            } else if (i == 1) {
167cabdff1aSopenharmony_ci                width = FFMIN(frame->linesize[i], FFALIGN(avctx->width, 2));
168cabdff1aSopenharmony_ci            }
169cabdff1aSopenharmony_ci
170cabdff1aSopenharmony_ci            for (j = 0; j < height; j++) {
171cabdff1aSopenharmony_ci                memcpy(dst, src, width);
172cabdff1aSopenharmony_ci                src += s->stride;
173cabdff1aSopenharmony_ci                dst += frame->linesize[i];
174cabdff1aSopenharmony_ci            }
175cabdff1aSopenharmony_ci        }
176cabdff1aSopenharmony_ci    }
177cabdff1aSopenharmony_ci}
178cabdff1aSopenharmony_ci
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_ci
181cabdff1aSopenharmony_civoid ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar(AVCodecContext *avctx,
182cabdff1aSopenharmony_ci                                                            MediaCodecDecContext *s,
183cabdff1aSopenharmony_ci                                                            uint8_t *data,
184cabdff1aSopenharmony_ci                                                            size_t size,
185cabdff1aSopenharmony_ci                                                            FFAMediaCodecBufferInfo *info,
186cabdff1aSopenharmony_ci                                                            AVFrame *frame)
187cabdff1aSopenharmony_ci{
188cabdff1aSopenharmony_ci    int i;
189cabdff1aSopenharmony_ci    uint8_t *src = NULL;
190cabdff1aSopenharmony_ci
191cabdff1aSopenharmony_ci    for (i = 0; i < 2; i++) {
192cabdff1aSopenharmony_ci        int height;
193cabdff1aSopenharmony_ci
194cabdff1aSopenharmony_ci        src = data + info->offset;
195cabdff1aSopenharmony_ci        if (i == 0) {
196cabdff1aSopenharmony_ci            height = avctx->height;
197cabdff1aSopenharmony_ci        } else if (i == 1) {
198cabdff1aSopenharmony_ci            height = avctx->height / 2;
199cabdff1aSopenharmony_ci
200cabdff1aSopenharmony_ci            src += (s->slice_height - s->crop_top / 2) * s->stride;
201cabdff1aSopenharmony_ci
202cabdff1aSopenharmony_ci            src += s->crop_top * s->stride;
203cabdff1aSopenharmony_ci            src += s->crop_left;
204cabdff1aSopenharmony_ci        }
205cabdff1aSopenharmony_ci
206cabdff1aSopenharmony_ci        if (frame->linesize[i] == s->stride) {
207cabdff1aSopenharmony_ci            memcpy(frame->data[i], src, height * s->stride);
208cabdff1aSopenharmony_ci        } else {
209cabdff1aSopenharmony_ci            int j, width;
210cabdff1aSopenharmony_ci            uint8_t *dst = frame->data[i];
211cabdff1aSopenharmony_ci
212cabdff1aSopenharmony_ci            if (i == 0) {
213cabdff1aSopenharmony_ci                width = avctx->width;
214cabdff1aSopenharmony_ci            } else if (i == 1) {
215cabdff1aSopenharmony_ci                width = FFMIN(frame->linesize[i], FFALIGN(avctx->width, 2));
216cabdff1aSopenharmony_ci            }
217cabdff1aSopenharmony_ci
218cabdff1aSopenharmony_ci            for (j = 0; j < height; j++) {
219cabdff1aSopenharmony_ci                memcpy(dst, src, width);
220cabdff1aSopenharmony_ci                src += s->stride;
221cabdff1aSopenharmony_ci                dst += frame->linesize[i];
222cabdff1aSopenharmony_ci            }
223cabdff1aSopenharmony_ci        }
224cabdff1aSopenharmony_ci    }
225cabdff1aSopenharmony_ci}
226cabdff1aSopenharmony_ci
227cabdff1aSopenharmony_ci/**
228cabdff1aSopenharmony_ci * The code handling the QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka
229cabdff1aSopenharmony_ci * color format is taken from the VLC project.
230cabdff1aSopenharmony_ci *
231cabdff1aSopenharmony_ci * VLC reference:
232cabdff1aSopenharmony_ci * http://git.videolan.org/?p=vlc.git;a=blob;f=modules/codec/omxil/qcom.c;hb=HEAD
233cabdff1aSopenharmony_ci *
234cabdff1aSopenharmony_ci * VLC copyright notice:
235cabdff1aSopenharmony_ci *
236cabdff1aSopenharmony_ci *****************************************************************************
237cabdff1aSopenharmony_ci * qcom.c : pixel format translation for Qualcomm tiled nv12
238cabdff1aSopenharmony_ci *****************************************************************************
239cabdff1aSopenharmony_ci * Copyright © 2012 Rafaël Carré
240cabdff1aSopenharmony_ci *
241cabdff1aSopenharmony_ci * Authors: Rafaël Carré <funman@videolanorg>
242cabdff1aSopenharmony_ci *
243cabdff1aSopenharmony_ci * This program is free software; you can redistribute it and/or modify it
244cabdff1aSopenharmony_ci * under the terms of the GNU Lesser General Public License as published by
245cabdff1aSopenharmony_ci * the Free Software Foundation; either version 2.1 of the License, or
246cabdff1aSopenharmony_ci * (at your option) any later version.
247cabdff1aSopenharmony_ci *
248cabdff1aSopenharmony_ci * This program is distributed in the hope that it will be useful,
249cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
250cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
251cabdff1aSopenharmony_ci * GNU Lesser General Public License for more details.
252cabdff1aSopenharmony_ci *
253cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public License
254cabdff1aSopenharmony_ci * along with this program; if not, write to the Free Software Foundation,
255cabdff1aSopenharmony_ci * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
256cabdff1aSopenharmony_ci *
257cabdff1aSopenharmony_ci */
258cabdff1aSopenharmony_ci
259cabdff1aSopenharmony_cistatic size_t qcom_tile_pos(size_t x, size_t y, size_t w, size_t h)
260cabdff1aSopenharmony_ci{
261cabdff1aSopenharmony_ci  size_t flim = x + (y & ~1) * w;
262cabdff1aSopenharmony_ci
263cabdff1aSopenharmony_ci  if (y & 1) {
264cabdff1aSopenharmony_ci    flim += (x & ~3) + 2;
265cabdff1aSopenharmony_ci  } else if ((h & 1) == 0 || y != (h - 1)) {
266cabdff1aSopenharmony_ci    flim += (x + 2) & ~3;
267cabdff1aSopenharmony_ci  }
268cabdff1aSopenharmony_ci
269cabdff1aSopenharmony_ci  return flim;
270cabdff1aSopenharmony_ci}
271cabdff1aSopenharmony_ci
272cabdff1aSopenharmony_civoid ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar_64x32Tile2m8ka(AVCodecContext *avctx,
273cabdff1aSopenharmony_ci                                                                           MediaCodecDecContext *s,
274cabdff1aSopenharmony_ci                                                                           uint8_t *data,
275cabdff1aSopenharmony_ci                                                                           size_t size,
276cabdff1aSopenharmony_ci                                                                           FFAMediaCodecBufferInfo *info,
277cabdff1aSopenharmony_ci                                                                           AVFrame *frame)
278cabdff1aSopenharmony_ci{
279cabdff1aSopenharmony_ci    size_t width = frame->width;
280cabdff1aSopenharmony_ci    size_t linesize = frame->linesize[0];
281cabdff1aSopenharmony_ci    size_t height = frame->height;
282cabdff1aSopenharmony_ci
283cabdff1aSopenharmony_ci    const size_t tile_w = (width - 1) / QCOM_TILE_WIDTH + 1;
284cabdff1aSopenharmony_ci    const size_t tile_w_align = (tile_w + 1) & ~1;
285cabdff1aSopenharmony_ci    const size_t tile_h_luma = (height - 1) / QCOM_TILE_HEIGHT + 1;
286cabdff1aSopenharmony_ci    const size_t tile_h_chroma = (height / 2 - 1) / QCOM_TILE_HEIGHT + 1;
287cabdff1aSopenharmony_ci
288cabdff1aSopenharmony_ci    size_t luma_size = tile_w_align * tile_h_luma * QCOM_TILE_SIZE;
289cabdff1aSopenharmony_ci    if((luma_size % QCOM_TILE_GROUP_SIZE) != 0)
290cabdff1aSopenharmony_ci        luma_size = (((luma_size - 1) / QCOM_TILE_GROUP_SIZE) + 1) * QCOM_TILE_GROUP_SIZE;
291cabdff1aSopenharmony_ci
292cabdff1aSopenharmony_ci    for(size_t y = 0; y < tile_h_luma; y++) {
293cabdff1aSopenharmony_ci        size_t row_width = width;
294cabdff1aSopenharmony_ci        for(size_t x = 0; x < tile_w; x++) {
295cabdff1aSopenharmony_ci            size_t tile_width = row_width;
296cabdff1aSopenharmony_ci            size_t tile_height = height;
297cabdff1aSopenharmony_ci            /* dest luma memory index for this tile */
298cabdff1aSopenharmony_ci            size_t luma_idx = y * QCOM_TILE_HEIGHT * linesize + x * QCOM_TILE_WIDTH;
299cabdff1aSopenharmony_ci            /* dest chroma memory index for this tile */
300cabdff1aSopenharmony_ci            /* XXX: remove divisions */
301cabdff1aSopenharmony_ci            size_t chroma_idx = (luma_idx / linesize) * linesize / 2 + (luma_idx % linesize);
302cabdff1aSopenharmony_ci
303cabdff1aSopenharmony_ci            /* luma source pointer for this tile */
304cabdff1aSopenharmony_ci            const uint8_t *src_luma  = data
305cabdff1aSopenharmony_ci                + qcom_tile_pos(x, y,tile_w_align, tile_h_luma) * QCOM_TILE_SIZE;
306cabdff1aSopenharmony_ci
307cabdff1aSopenharmony_ci            /* chroma source pointer for this tile */
308cabdff1aSopenharmony_ci            const uint8_t *src_chroma = data + luma_size
309cabdff1aSopenharmony_ci                + qcom_tile_pos(x, y/2, tile_w_align, tile_h_chroma) * QCOM_TILE_SIZE;
310cabdff1aSopenharmony_ci            if (y & 1)
311cabdff1aSopenharmony_ci                src_chroma += QCOM_TILE_SIZE/2;
312cabdff1aSopenharmony_ci
313cabdff1aSopenharmony_ci            /* account for right columns */
314cabdff1aSopenharmony_ci            if (tile_width > QCOM_TILE_WIDTH)
315cabdff1aSopenharmony_ci                tile_width = QCOM_TILE_WIDTH;
316cabdff1aSopenharmony_ci
317cabdff1aSopenharmony_ci            /* account for bottom rows */
318cabdff1aSopenharmony_ci            if (tile_height > QCOM_TILE_HEIGHT)
319cabdff1aSopenharmony_ci                tile_height = QCOM_TILE_HEIGHT;
320cabdff1aSopenharmony_ci
321cabdff1aSopenharmony_ci            tile_height /= 2;
322cabdff1aSopenharmony_ci            while (tile_height--) {
323cabdff1aSopenharmony_ci                memcpy(frame->data[0] + luma_idx, src_luma, tile_width);
324cabdff1aSopenharmony_ci                src_luma += QCOM_TILE_WIDTH;
325cabdff1aSopenharmony_ci                luma_idx += linesize;
326cabdff1aSopenharmony_ci
327cabdff1aSopenharmony_ci                memcpy(frame->data[0] + luma_idx, src_luma, tile_width);
328cabdff1aSopenharmony_ci                src_luma += QCOM_TILE_WIDTH;
329cabdff1aSopenharmony_ci                luma_idx += linesize;
330cabdff1aSopenharmony_ci
331cabdff1aSopenharmony_ci                memcpy(frame->data[1] + chroma_idx, src_chroma, tile_width);
332cabdff1aSopenharmony_ci                src_chroma += QCOM_TILE_WIDTH;
333cabdff1aSopenharmony_ci                chroma_idx += linesize;
334cabdff1aSopenharmony_ci            }
335cabdff1aSopenharmony_ci            row_width -= QCOM_TILE_WIDTH;
336cabdff1aSopenharmony_ci        }
337cabdff1aSopenharmony_ci        height -= QCOM_TILE_HEIGHT;
338cabdff1aSopenharmony_ci    }
339cabdff1aSopenharmony_ci}
340