tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

mediacodec_sw_buffer.c (11894B)


      1 /*
      2 * Android MediaCodec software buffer copy functions
      3 *
      4 * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
      5 *
      6 * This file is part of FFmpeg.
      7 *
      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.
     12 *
     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.
     17 *
     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
     21 */
     22 
     23 #include <string.h>
     24 #include <sys/types.h>
     25 
     26 #include "libavutil/frame.h"
     27 #include "libavutil/mem.h"
     28 
     29 #include "avcodec.h"
     30 #include "mediacodec_wrapper.h"
     31 #include "mediacodec_sw_buffer.h"
     32 #include "mediacodecdec_common.h"
     33 
     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)
     38 
     39 /**
     40 * The code handling the various YUV color formats is taken from the
     41 * GStreamer project.
     42 *
     43 * Gstreamer reference:
     44 * https://cgit.freedesktop.org/gstreamer/gst-plugins-bad/tree/sys/androidmedia/
     45 *
     46 * Copyright (C) 2012, Collabora Ltd.
     47 *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
     48 *
     49 * Copyright (C) 2012, Rafaël Carré <funman@videolanorg>
     50 *
     51 * Copyright (C) 2015, Sebastian Dröge <sebastian@centricular.com>
     52 *
     53 * Copyright (C) 2014-2015, Collabora Ltd.
     54 *   Author: Matthieu Bouron <matthieu.bouron@gcollabora.com>
     55 *
     56 * Copyright (C) 2015, Edward Hervey
     57 *   Author: Edward Hervey <bilboed@gmail.com>
     58 *
     59 * Copyright (C) 2015, Matthew Waters <matthew@centricular.com>
     60 *
     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.
     65 *
     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.
     70 *
     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
     74 *
     75 */
     76 void ff_mediacodec_sw_buffer_copy_yuv420_planar(AVCodecContext *avctx,
     77                                                MediaCodecDecContext *s,
     78                                                uint8_t *data,
     79                                                size_t size,
     80                                                FFAMediaCodecBufferInfo *info,
     81                                                AVFrame *frame)
     82 {
     83    int i;
     84    uint8_t *src = NULL;
     85 
     86    for (i = 0; i < 3; i++) {
     87        int stride = s->stride;
     88        int height;
     89 
     90        src = data + info->offset;
     91        if (i == 0) {
     92            height = avctx->height;
     93 
     94            src += s->crop_top * s->stride;
     95            src += s->crop_left;
     96        } else {
     97            height = avctx->height / 2;
     98            stride = (s->stride + 1) / 2;
     99 
    100            src += s->slice_height * s->stride;
    101 
    102            if (i == 2) {
    103                src += ((s->slice_height + 1) / 2) * stride;
    104            }
    105 
    106            src += s->crop_top * stride;
    107            src += (s->crop_left / 2);
    108        }
    109 
    110        if (frame->linesize[i] == stride) {
    111            memcpy(frame->data[i], src, height * stride);
    112        } else {
    113            int j, width;
    114            uint8_t *dst = frame->data[i];
    115 
    116            if (i == 0) {
    117                width = avctx->width;
    118            } else if (i >= 1) {
    119                width = FFMIN(frame->linesize[i], FFALIGN(avctx->width, 2) / 2);
    120            }
    121 
    122            for (j = 0; j < height; j++) {
    123                memcpy(dst, src, width);
    124                src += stride;
    125                dst += frame->linesize[i];
    126            }
    127        }
    128    }
    129 }
    130 
    131 void ff_mediacodec_sw_buffer_copy_yuv420_semi_planar(AVCodecContext *avctx,
    132                                                     MediaCodecDecContext *s,
    133                                                     uint8_t *data,
    134                                                     size_t size,
    135                                                     FFAMediaCodecBufferInfo *info,
    136                                                     AVFrame *frame)
    137 {
    138    int i;
    139    uint8_t *src = NULL;
    140 
    141    for (i = 0; i < 2; i++) {
    142        int height;
    143 
    144        src = data + info->offset;
    145        if (i == 0) {
    146            height = avctx->height;
    147 
    148            src += s->crop_top * s->stride;
    149            src += s->crop_left;
    150        } else if (i == 1) {
    151            height = avctx->height / 2;
    152 
    153            src += s->slice_height * s->stride;
    154            src += s->crop_top * s->stride;
    155            src += s->crop_left;
    156        }
    157 
    158        if (frame->linesize[i] == s->stride) {
    159            memcpy(frame->data[i], src, height * s->stride);
    160        } else {
    161            int j, width;
    162            uint8_t *dst = frame->data[i];
    163 
    164            if (i == 0) {
    165                width = avctx->width;
    166            } else if (i == 1) {
    167                width = FFMIN(frame->linesize[i], FFALIGN(avctx->width, 2));
    168            }
    169 
    170            for (j = 0; j < height; j++) {
    171                memcpy(dst, src, width);
    172                src += s->stride;
    173                dst += frame->linesize[i];
    174            }
    175        }
    176    }
    177 }
    178 
    179 
    180 
    181 void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar(AVCodecContext *avctx,
    182                                                            MediaCodecDecContext *s,
    183                                                            uint8_t *data,
    184                                                            size_t size,
    185                                                            FFAMediaCodecBufferInfo *info,
    186                                                            AVFrame *frame)
    187 {
    188    int i;
    189    uint8_t *src = NULL;
    190 
    191    for (i = 0; i < 2; i++) {
    192        int height;
    193 
    194        src = data + info->offset;
    195        if (i == 0) {
    196            height = avctx->height;
    197        } else if (i == 1) {
    198            height = avctx->height / 2;
    199 
    200            src += (s->slice_height - s->crop_top / 2) * s->stride;
    201 
    202            src += s->crop_top * s->stride;
    203            src += s->crop_left;
    204        }
    205 
    206        if (frame->linesize[i] == s->stride) {
    207            memcpy(frame->data[i], src, height * s->stride);
    208        } else {
    209            int j, width;
    210            uint8_t *dst = frame->data[i];
    211 
    212            if (i == 0) {
    213                width = avctx->width;
    214            } else if (i == 1) {
    215                width = FFMIN(frame->linesize[i], FFALIGN(avctx->width, 2));
    216            }
    217 
    218            for (j = 0; j < height; j++) {
    219                memcpy(dst, src, width);
    220                src += s->stride;
    221                dst += frame->linesize[i];
    222            }
    223        }
    224    }
    225 }
    226 
    227 /**
    228 * The code handling the QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka
    229 * color format is taken from the VLC project.
    230 *
    231 * VLC reference:
    232 * http://git.videolan.org/?p=vlc.git;a=blob;f=modules/codec/omxil/qcom.c;hb=HEAD
    233 *
    234 * VLC copyright notice:
    235 *
    236 *****************************************************************************
    237 * qcom.c : pixel format translation for Qualcomm tiled nv12
    238 *****************************************************************************
    239 * Copyright © 2012 Rafaël Carré
    240 *
    241 * Authors: Rafaël Carré <funman@videolanorg>
    242 *
    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.
    247 *
    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.
    252 *
    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.
    256 *
    257 */
    258 
    259 static size_t qcom_tile_pos(size_t x, size_t y, size_t w, size_t h)
    260 {
    261  size_t flim = x + (y & ~1) * w;
    262 
    263  if (y & 1) {
    264    flim += (x & ~3) + 2;
    265  } else if ((h & 1) == 0 || y != (h - 1)) {
    266    flim += (x + 2) & ~3;
    267  }
    268 
    269  return flim;
    270 }
    271 
    272 void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar_64x32Tile2m8ka(AVCodecContext *avctx,
    273                                                                           MediaCodecDecContext *s,
    274                                                                           uint8_t *data,
    275                                                                           size_t size,
    276                                                                           FFAMediaCodecBufferInfo *info,
    277                                                                           AVFrame *frame)
    278 {
    279    size_t width = frame->width;
    280    size_t linesize = frame->linesize[0];
    281    size_t height = frame->height;
    282 
    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;
    287 
    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;
    291 
    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);
    302 
    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;
    306 
    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;
    310            if (y & 1)
    311                src_chroma += QCOM_TILE_SIZE/2;
    312 
    313            /* account for right columns */
    314            if (tile_width > QCOM_TILE_WIDTH)
    315                tile_width = QCOM_TILE_WIDTH;
    316 
    317            /* account for bottom rows */
    318            if (tile_height > QCOM_TILE_HEIGHT)
    319                tile_height = QCOM_TILE_HEIGHT;
    320 
    321            tile_height /= 2;
    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;
    326 
    327                memcpy(frame->data[0] + luma_idx, src_luma, tile_width);
    328                src_luma += QCOM_TILE_WIDTH;
    329                luma_idx += linesize;
    330 
    331                memcpy(frame->data[1] + chroma_idx, src_chroma, tile_width);
    332                src_chroma += QCOM_TILE_WIDTH;
    333                chroma_idx += linesize;
    334            }
    335            row_width -= QCOM_TILE_WIDTH;
    336        }
    337        height -= QCOM_TILE_HEIGHT;
    338    }
    339 }