FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mediacodec_sw_buffer.c
Go to the documentation of this file.
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 "mediacodecdec.h"
31 #include "mediacodec_wrapper.h"
32 #include "mediacodec_sw_buffer.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  */
78  uint8_t *data,
79  size_t size,
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 
133  uint8_t *data,
134  size_t size,
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 
183  uint8_t *data,
184  size_t size,
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 
274  uint8_t *data,
275  size_t size,
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 }
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:631
This structure describes decoded (raw) audio or video data.
Definition: frame.h:184
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
#define QCOM_TILE_SIZE
memory handling functions
void ff_mediacodec_sw_buffer_copy_yuv420_semi_planar(AVCodecContext *avctx, MediaCodecDecContext *s, uint8_t *data, size_t size, FFAMediaCodecBufferInfo *info, AVFrame *frame)
void ff_mediacodec_sw_buffer_copy_yuv420_planar(AVCodecContext *avctx, MediaCodecDecContext *s, uint8_t *data, size_t size, FFAMediaCodecBufferInfo *info, AVFrame *frame)
The code handling the various YUV color formats is taken from the GStreamer project.
uint8_t
static AVFrame * frame
#define height
#define QCOM_TILE_HEIGHT
ptrdiff_t size
Definition: opengl_enc.c:101
#define FFALIGN(x, a)
Definition: macros.h:48
int width
width and height of the video frame
Definition: frame.h:236
reference-counted frame API
void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar(AVCodecContext *avctx, MediaCodecDecContext *s, uint8_t *data, size_t size, FFAMediaCodecBufferInfo *info, AVFrame *frame)
#define QCOM_TILE_WIDTH
#define FFMIN(a, b)
Definition: common.h:96
#define width
int width
picture width / height.
Definition: avcodec.h:1836
void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar_64x32Tile2m8ka(AVCodecContext *avctx, MediaCodecDecContext *s, uint8_t *data, size_t size, FFAMediaCodecBufferInfo *info, AVFrame *frame)
static size_t qcom_tile_pos(size_t x, size_t y, size_t w, size_t h)
The code handling the QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka color format is taken from the ...
#define src
Definition: vp9dsp.c:530
Libavcodec external API header.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:215
main external API structure.
Definition: avcodec.h:1649
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:198
GLint GLenum GLboolean GLsizei stride
Definition: opengl_enc.c:105
int height
Definition: frame.h:236
#define stride
#define QCOM_TILE_GROUP_SIZE