2 * Android MediaCodec software buffer copy functions
4 * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
6 * This file is part of FFmpeg.
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.
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.
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
24 #include <sys/types.h>
26 #include "libavutil/frame.h"
27 #include "libavutil/mem.h"
30 #include "mediacodecdec.h"
31 #include "mediacodec_wrapper.h"
32 #include "mediacodec_sw_buffer.h"
34 #define QCOM_TILE_WIDTH 64
35 #define QCOM_TILE_HEIGHT 32
36 #define QCOM_TILE_SIZE (QCOM_TILE_WIDTH * QCOM_TILE_HEIGHT)
37 #define QCOM_TILE_GROUP_SIZE (4 * QCOM_TILE_SIZE)
40 * The code handling the various YUV color formats is taken from the
43 * Gstreamer reference:
44 * https://cgit.freedesktop.org/gstreamer/gst-plugins-bad/tree/sys/androidmedia/
46 * Copyright (C) 2012, Collabora Ltd.
47 * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
49 * Copyright (C) 2012, Rafaël Carré <funman@videolanorg>
51 * Copyright (C) 2015, Sebastian Dröge <sebastian@centricular.com>
53 * Copyright (C) 2014-2015, Collabora Ltd.
54 * Author: Matthieu Bouron <matthieu.bouron@gcollabora.com>
56 * Copyright (C) 2015, Edward Hervey
57 * Author: Edward Hervey <bilboed@gmail.com>
59 * Copyright (C) 2015, Matthew Waters <matthew@centricular.com>
61 * This library is free software; you can redistribute it and/or
62 * modify it under the terms of the GNU Lesser General Public
63 * License as published by the Free Software Foundation
64 * version 2.1 of the License.
66 * This library is distributed in the hope that it will be useful,
67 * but WITHOUT ANY WARRANTY; without even the implied warranty of
68 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
69 * Lesser General Public License for more details.
71 * You should have received a copy of the GNU Lesser General Public
72 * License along with this library; if not, write to the Free Software
73 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
76 void ff_mediacodec_sw_buffer_copy_yuv420_planar(AVCodecContext *avctx,
77 MediaCodecDecContext *s,
80 FFAMediaCodecBufferInfo *info,
86 for (i = 0; i < 3; i++) {
87 int stride = s->stride;
90 src = data + info->offset;
92 height = avctx->height;
94 src += s->crop_top * s->stride;
97 height = avctx->height / 2;
98 stride = (s->stride + 1) / 2;
100 src += s->slice_height * s->stride;
103 src += ((s->slice_height + 1) / 2) * stride;
106 src += s->crop_top * stride;
107 src += (s->crop_left / 2);
110 if (frame->linesize[i] == stride) {
111 memcpy(frame->data[i], src, height * stride);
114 uint8_t *dst = frame->data[i];
117 width = avctx->width;
119 width = FFMIN(frame->linesize[i], FFALIGN(avctx->width, 2) / 2);
122 for (j = 0; j < height; j++) {
123 memcpy(dst, src, width);
125 dst += frame->linesize[i];
131 void ff_mediacodec_sw_buffer_copy_yuv420_semi_planar(AVCodecContext *avctx,
132 MediaCodecDecContext *s,
135 FFAMediaCodecBufferInfo *info,
141 for (i = 0; i < 2; i++) {
144 src = data + info->offset;
146 height = avctx->height;
148 src += s->crop_top * s->stride;
151 height = avctx->height / 2;
153 src += s->slice_height * s->stride;
154 src += s->crop_top * s->stride;
158 if (frame->linesize[i] == s->stride) {
159 memcpy(frame->data[i], src, height * s->stride);
162 uint8_t *dst = frame->data[i];
165 width = avctx->width;
167 width = FFMIN(frame->linesize[i], FFALIGN(avctx->width, 2));
170 for (j = 0; j < height; j++) {
171 memcpy(dst, src, width);
173 dst += frame->linesize[i];
181 void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar(AVCodecContext *avctx,
182 MediaCodecDecContext *s,
185 FFAMediaCodecBufferInfo *info,
191 for (i = 0; i < 2; i++) {
194 src = data + info->offset;
196 height = avctx->height;
198 height = avctx->height / 2;
200 src += (s->slice_height - s->crop_top / 2) * s->stride;
202 src += s->crop_top * s->stride;
206 if (frame->linesize[i] == s->stride) {
207 memcpy(frame->data[i], src, height * s->stride);
210 uint8_t *dst = frame->data[i];
213 width = avctx->width;
215 width = FFMIN(frame->linesize[i], FFALIGN(avctx->width, 2));
218 for (j = 0; j < height; j++) {
219 memcpy(dst, src, width);
221 dst += frame->linesize[i];
228 * The code handling the QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka
229 * color format is taken from the VLC project.
232 * http://git.videolan.org/?p=vlc.git;a=blob;f=modules/codec/omxil/qcom.c;hb=HEAD
234 * VLC copyright notice:
236 *****************************************************************************
237 * qcom.c : pixel format translation for Qualcomm tiled nv12
238 *****************************************************************************
239 * Copyright © 2012 Rafaël Carré
241 * Authors: Rafaël Carré <funman@videolanorg>
243 * This program is free software; you can redistribute it and/or modify it
244 * under the terms of the GNU Lesser General Public License as published by
245 * the Free Software Foundation; either version 2.1 of the License, or
246 * (at your option) any later version.
248 * This program is distributed in the hope that it will be useful,
249 * but WITHOUT ANY WARRANTY; without even the implied warranty of
250 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
251 * GNU Lesser General Public License for more details.
253 * You should have received a copy of the GNU Lesser General Public License
254 * along with this program; if not, write to the Free Software Foundation,
255 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
259 static size_t qcom_tile_pos(size_t x, size_t y, size_t w, size_t h)
261 size_t flim = x + (y & ~1) * w;
264 flim += (x & ~3) + 2;
265 } else if ((h & 1) == 0 || y != (h - 1)) {
266 flim += (x + 2) & ~3;
272 void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar_64x32Tile2m8ka(AVCodecContext *avctx,
273 MediaCodecDecContext *s,
276 FFAMediaCodecBufferInfo *info,
279 size_t width = frame->width;
280 size_t linesize = frame->linesize[0];
281 size_t height = frame->height;
283 const size_t tile_w = (width - 1) / QCOM_TILE_WIDTH + 1;
284 const size_t tile_w_align = (tile_w + 1) & ~1;
285 const size_t tile_h_luma = (height - 1) / QCOM_TILE_HEIGHT + 1;
286 const size_t tile_h_chroma = (height / 2 - 1) / QCOM_TILE_HEIGHT + 1;
288 size_t luma_size = tile_w_align * tile_h_luma * QCOM_TILE_SIZE;
289 if((luma_size % QCOM_TILE_GROUP_SIZE) != 0)
290 luma_size = (((luma_size - 1) / QCOM_TILE_GROUP_SIZE) + 1) * QCOM_TILE_GROUP_SIZE;
292 for(size_t y = 0; y < tile_h_luma; y++) {
293 size_t row_width = width;
294 for(size_t x = 0; x < tile_w; x++) {
295 size_t tile_width = row_width;
296 size_t tile_height = height;
297 /* dest luma memory index for this tile */
298 size_t luma_idx = y * QCOM_TILE_HEIGHT * linesize + x * QCOM_TILE_WIDTH;
299 /* dest chroma memory index for this tile */
300 /* XXX: remove divisions */
301 size_t chroma_idx = (luma_idx / linesize) * linesize / 2 + (luma_idx % linesize);
303 /* luma source pointer for this tile */
304 const uint8_t *src_luma = data
305 + qcom_tile_pos(x, y,tile_w_align, tile_h_luma) * QCOM_TILE_SIZE;
307 /* chroma source pointer for this tile */
308 const uint8_t *src_chroma = data + luma_size
309 + qcom_tile_pos(x, y/2, tile_w_align, tile_h_chroma) * QCOM_TILE_SIZE;
311 src_chroma += QCOM_TILE_SIZE/2;
313 /* account for right columns */
314 if (tile_width > QCOM_TILE_WIDTH)
315 tile_width = QCOM_TILE_WIDTH;
317 /* account for bottom rows */
318 if (tile_height > QCOM_TILE_HEIGHT)
319 tile_height = QCOM_TILE_HEIGHT;
322 while (tile_height--) {
323 memcpy(frame->data[0] + luma_idx, src_luma, tile_width);
324 src_luma += QCOM_TILE_WIDTH;
325 luma_idx += linesize;
327 memcpy(frame->data[0] + luma_idx, src_luma, tile_width);
328 src_luma += QCOM_TILE_WIDTH;
329 luma_idx += linesize;
331 memcpy(frame->data[1] + chroma_idx, src_chroma, tile_width);
332 src_chroma += QCOM_TILE_WIDTH;
333 chroma_idx += linesize;
335 row_width -= QCOM_TILE_WIDTH;
337 height -= QCOM_TILE_HEIGHT;