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