vda_h264_dec.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Xidorn Quan
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /**
22  * @file
23  * H.264 decoder via VDA
24  * @author Xidorn Quan <quanxunzhen@gmail.com>
25  */
26 
27 #include <string.h>
28 #include <CoreFoundation/CoreFoundation.h>
29 
30 #include "vda.h"
31 #include "h264.h"
32 #include "avcodec.h"
33 
34 #ifndef kCFCoreFoundationVersionNumber10_7
35 #define kCFCoreFoundationVersionNumber10_7 635.00
36 #endif
37 
39 
40 static const enum AVPixelFormat vda_pixfmts_prior_10_7[] = {
44 };
45 
46 static const enum AVPixelFormat vda_pixfmts[] = {
52 };
53 
54 typedef struct {
57  struct vda_context vda_ctx;
60 
61 static enum AVPixelFormat get_format(struct AVCodecContext *avctx,
62  const enum AVPixelFormat *fmt)
63 {
64  return AV_PIX_FMT_VDA_VLD;
65 }
66 
67 typedef struct {
68  CVPixelBufferRef cv_buffer;
70 
71 static void release_buffer(void *opaque, uint8_t *data)
72 {
73  VDABufferContext *context = opaque;
74  CVPixelBufferUnlockBaseAddress(context->cv_buffer, 0);
75  CVPixelBufferRelease(context->cv_buffer);
76  av_free(context);
77 }
78 
79 static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flag)
80 {
81  VDABufferContext *context = av_mallocz(sizeof(VDABufferContext));
83  if (!context || !buffer) {
84  av_free(context);
85  return AVERROR(ENOMEM);
86  }
87 
88  pic->buf[0] = buffer;
89  pic->data[0] = (void *)1;
90  return 0;
91 }
92 
93 static int vdadec_decode(AVCodecContext *avctx,
94  void *data, int *got_frame, AVPacket *avpkt)
95 {
96  VDADecoderContext *ctx = avctx->priv_data;
97  AVFrame *pic = data;
98  int ret;
99 
100  ret = ff_h264_decoder.decode(avctx, data, got_frame, avpkt);
101  if (*got_frame) {
102  AVBufferRef *buffer = pic->buf[0];
103  VDABufferContext *context = av_buffer_get_opaque(buffer);
104  CVPixelBufferRef cv_buffer = (CVPixelBufferRef)pic->data[3];
105  CVPixelBufferLockBaseAddress(cv_buffer, 0);
106  context->cv_buffer = cv_buffer;
107  pic->format = ctx->pix_fmt;
108  if (CVPixelBufferIsPlanar(cv_buffer)) {
109  int i, count = CVPixelBufferGetPlaneCount(cv_buffer);
110  av_assert0(count < 4);
111  for (i = 0; i < count; i++) {
112  pic->data[i] = CVPixelBufferGetBaseAddressOfPlane(cv_buffer, i);
113  pic->linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(cv_buffer, i);
114  }
115  } else {
116  pic->data[0] = CVPixelBufferGetBaseAddress(cv_buffer);
117  pic->linesize[0] = CVPixelBufferGetBytesPerRow(cv_buffer);
118  }
119  }
120  avctx->pix_fmt = ctx->pix_fmt;
121 
122  return ret;
123 }
124 
126 {
127  VDADecoderContext *ctx = avctx->priv_data;
128  /* release buffers and decoder */
130  /* close H.264 decoder */
131  if (ctx->h264_initialized)
132  ff_h264_decoder.close(avctx);
133  return 0;
134 }
135 
137 {
138  AVCodecParserContext *parser;
139  uint8_t *pout;
140  int psize;
141  int index;
142  H264Context *h;
143  int ret = -1;
144 
145  /* init parser & parse file */
146  parser = av_parser_init(avctx->codec->id);
147  if (!parser) {
148  av_log(avctx, AV_LOG_ERROR, "Failed to open H.264 parser.\n");
149  goto final;
150  }
152  index = av_parser_parse2(parser, avctx, &pout, &psize, NULL, 0, 0, 0, 0);
153  if (index < 0) {
154  av_log(avctx, AV_LOG_ERROR, "Failed to parse this file.\n");
155  goto release_parser;
156  }
157 
158  /* check if support */
159  h = parser->priv_data;
160  switch (h->sps.bit_depth_luma) {
161  case 8:
162  if (!CHROMA444(h) && !CHROMA422(h)) {
163  // only this will H.264 decoder switch to hwaccel
164  ret = 0;
165  break;
166  }
167  default:
168  av_log(avctx, AV_LOG_ERROR, "Unsupported file.\n");
169  }
170 
171 release_parser:
172  av_parser_close(parser);
173 
174 final:
175  return ret;
176 }
177 
179 {
180  VDADecoderContext *ctx = avctx->priv_data;
181  struct vda_context *vda_ctx = &ctx->vda_ctx;
182  OSStatus status;
183  int ret;
184 
185  ctx->h264_initialized = 0;
186 
187  /* init pix_fmts of codec */
188  if (!ff_h264_vda_decoder.pix_fmts) {
189  if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber10_7)
190  ff_h264_vda_decoder.pix_fmts = vda_pixfmts_prior_10_7;
191  else
192  ff_h264_vda_decoder.pix_fmts = vda_pixfmts;
193  }
194 
195  /* check if VDA supports this file */
196  if (check_format(avctx) < 0)
197  goto failed;
198 
199  /* init vda */
200  memset(vda_ctx, 0, sizeof(struct vda_context));
201  vda_ctx->width = avctx->width;
202  vda_ctx->height = avctx->height;
203  vda_ctx->format = 'avc1';
204  vda_ctx->use_sync_decoding = 1;
205  ctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts);
206  switch (ctx->pix_fmt) {
207  case AV_PIX_FMT_UYVY422:
208  vda_ctx->cv_pix_fmt_type = '2vuy';
209  break;
210  case AV_PIX_FMT_YUYV422:
211  vda_ctx->cv_pix_fmt_type = 'yuvs';
212  break;
213  case AV_PIX_FMT_NV12:
214  vda_ctx->cv_pix_fmt_type = '420v';
215  break;
216  case AV_PIX_FMT_YUV420P:
217  vda_ctx->cv_pix_fmt_type = 'y420';
218  break;
219  default:
220  av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format: %d\n", avctx->pix_fmt);
221  goto failed;
222  }
223  status = ff_vda_create_decoder(vda_ctx,
224  avctx->extradata, avctx->extradata_size);
225  if (status != kVDADecoderNoErr) {
226  av_log(avctx, AV_LOG_ERROR,
227  "Failed to init VDA decoder: %d.\n", status);
228  goto failed;
229  }
230  avctx->hwaccel_context = vda_ctx;
231 
232  /* changes callback functions */
233  avctx->get_format = get_format;
234  avctx->get_buffer2 = get_buffer2;
235 #if FF_API_GET_BUFFER
236  // force the old get_buffer to be empty
237  avctx->get_buffer = NULL;
238 #endif
239 
240  /* init H.264 decoder */
241  ret = ff_h264_decoder.init(avctx);
242  if (ret < 0) {
243  av_log(avctx, AV_LOG_ERROR, "Failed to open H.264 decoder.\n");
244  goto failed;
245  }
246  ctx->h264_initialized = 1;
247 
248  return 0;
249 
250 failed:
251  vdadec_close(avctx);
252  return -1;
253 }
254 
255 static void vdadec_flush(AVCodecContext *avctx)
256 {
257  return ff_h264_decoder.flush(avctx);
258 }
259 
260 AVCodec ff_h264_vda_decoder = {
261  .name = "h264_vda",
262  .type = AVMEDIA_TYPE_VIDEO,
263  .id = AV_CODEC_ID_H264,
264  .priv_data_size = sizeof(VDADecoderContext),
265  .init = vdadec_init,
266  .close = vdadec_close,
268  .capabilities = CODEC_CAP_DELAY,
269  .flush = vdadec_flush,
270  .long_name = NULL_IF_CONFIG_SMALL("H.264 (VDA acceleration)"),
271 };
enum AVPixelFormat(* get_format)(struct AVCodecContext *s, const enum AVPixelFormat *fmt)
callback to negotiate the pixelFormat
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition: pixfmt.h:85
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
const struct AVCodec * codec
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
#define CHROMA444(h)
Definition: h264.h:92
const char * fmt
Definition: avisynth_c.h:669
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:343
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
AVCodec ff_h264_vda_decoder
Definition: vda_h264_dec.c:260
H264Context.
Definition: h264.h:260
int format
The frame format.
Definition: vda.h:104
OSType cv_pix_fmt_type
The pixel format for output image buffers.
Definition: vda.h:112
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
H264Context h264ctx
Definition: vda_h264_dec.c:55
uint8_t
#define av_cold
Definition: attributes.h:78
void * hwaccel_context
Hardware accelerator context.
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
static enum AVPixelFormat get_format(struct AVCodecContext *avctx, const enum AVPixelFormat *fmt)
Definition: vda_h264_dec.c:61
enum AVPixelFormat pix_fmt
Definition: v4l.c:63
int width
The frame width.
Definition: vda.h:88
static av_cold int vdadec_init(AVCodecContext *avctx)
Definition: vda_h264_dec.c:178
CVPixelBufferRef cv_buffer
The Core Video pixel buffer that contains the current image data.
Definition: vda.h:72
static enum AVPixelFormat vda_pixfmts[]
Definition: vda_h264_dec.c:46
H.264 / AVC / MPEG4 part10 codec.
enum AVCodecID id
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
#define CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
#define PARSER_FLAG_COMPLETE_FRAMES
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Spectrum Plot time data
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:93
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
const char * name
Name of the codec implementation.
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
This structure is used to provide the necessary configurations and data to the VDA FFmpeg HWAccel imp...
Definition: vda.h:57
external API header
static av_cold int vdadec_close(AVCodecContext *avctx)
Definition: vda_h264_dec.c:125
enum AVPixelFormat * pix_fmts
array of supported pixel formats, or NULL if unknown, array is terminated by -1
int av_parser_parse2(AVCodecParserContext *s, AVCodecContext *avctx, uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size, int64_t pts, int64_t dts, int64_t pos)
Parse a packet.
Definition: parser.c:112
ret
Definition: avfilter.c:821
int width
picture width / height.
SPS sps
current sps
Definition: h264.h:360
void av_parser_close(AVCodecParserContext *s)
Definition: parser.c:202
enum AVPixelFormat pix_fmt
Definition: vda_h264_dec.c:58
struct vda_context vda_ctx
Definition: vda_h264_dec.c:57
static void flush(AVCodecContext *avctx)
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:134
NULL
Definition: eval.c:55
CVPixelBufferRef cv_buffer
Definition: vda_h264_dec.c:68
AVCodecParserContext * av_parser_init(int codec_id)
Definition: parser.c:41
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
Public libavcodec VDA header.
int ff_vda_destroy_decoder(struct vda_context *vda_ctx)
Destroy the video decoder.
Definition: vda_h264.c:217
main external API structure.
AVCodec ff_h264_decoder
Definition: h264.c:5040
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:375
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:69
static enum AVPixelFormat vda_pixfmts_prior_10_7[]
Definition: vda_h264_dec.c:40
int(* close)(AVCodecContext *)
void * av_buffer_get_opaque(const AVBufferRef *buf)
int(* get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags)
This callback is called at the beginning of each frame to get data buffer(s) for it.
#define CHROMA422(h)
Definition: h264.h:91
int index
Definition: gxfenc.c:89
synthesis window for stochastic i
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
int use_sync_decoding
Use the hardware decoder in synchronous mode.
Definition: vda.h:80
static void vdadec_flush(AVCodecContext *avctx)
Definition: vda_h264_dec.c:255
#define kCFCoreFoundationVersionNumber10_7
Definition: vda_h264_dec.c:35
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
A reference to a data buffer.
Definition: buffer.h:81
hardware decoding through VDA
Definition: pixfmt.h:160
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:68
int(* decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt)
static void release_buffer(void *opaque, uint8_t *data)
Definition: vda_h264_dec.c:71
void(* flush)(AVCodecContext *)
Flush buffers.
int(* init)(AVCodecContext *)
the buffer and buffer reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFilterBuffer structures They must not be accessed but through references stored in AVFilterBufferRef structures Several references can point to the same buffer
int bit_depth_luma
bit_depth_luma_minus8 + 8
Definition: h264.h:203
static av_cold int check_format(AVCodecContext *avctx)
Definition: vda_h264_dec.c:136
int ff_vda_create_decoder(struct vda_context *vda_ctx, uint8_t *extradata, int extradata_size)
Create the video decoder.
Definition: vda_h264.c:130
static int vdadec_decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: vda_h264_dec.c:93
static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flag)
Definition: vda_h264_dec.c:79
void INT64 INT64 count
Definition: avisynth_c.h:594
static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: crystalhd.c:868
int height
The frame height.
Definition: vda.h:96
AVPixelFormat
Pixel format.
Definition: pixfmt.h:66
This structure stores compressed data.