2 * Copyright (c) 2012, Xidorn Quan
4 * This file is part of FFmpeg.
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.
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.
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
23 * H.264 decoder via VDA
24 * @author Xidorn Quan <quanxunzhen@gmail.com>
28 #include <CoreFoundation/CoreFoundation.h>
34 #ifndef kCFCoreFoundationVersionNumber10_7
35 #define kCFCoreFoundationVersionNumber10_7 635.00
38 extern AVCodec ff_h264_decoder
, ff_h264_vda_decoder
;
40 static const enum AVPixelFormat vda_pixfmts_prior_10_7
[] = {
46 static const enum AVPixelFormat vda_pixfmts
[] = {
57 struct vda_context vda_ctx
;
58 enum AVPixelFormat pix_fmt
;
60 /* for backing-up fields set by user.
61 * we have to gain full control of such fields here */
62 void *hwaccel_context
;
63 enum AVPixelFormat (*get_format
)(struct AVCodecContext
*s
, const enum AVPixelFormat
* fmt
);
64 int (*get_buffer2
)(struct AVCodecContext
*s
, AVFrame
*frame
, int flags
);
66 int (*get_buffer
)(struct AVCodecContext
*c
, AVFrame
*pic
);
70 static enum AVPixelFormat
get_format(struct AVCodecContext
*avctx
,
71 const enum AVPixelFormat
*fmt
)
73 return AV_PIX_FMT_VDA_VLD
;
77 CVPixelBufferRef cv_buffer
;
80 static void release_buffer(void *opaque
, uint8_t *data
)
82 VDABufferContext
*context
= opaque
;
83 CVPixelBufferUnlockBaseAddress(context
->cv_buffer
, 0);
84 CVPixelBufferRelease(context
->cv_buffer
);
88 static int get_buffer2(AVCodecContext
*avctx
, AVFrame
*pic
, int flag
)
90 VDABufferContext
*context
= av_mallocz(sizeof(VDABufferContext
));
91 AVBufferRef
*buffer
= av_buffer_create(NULL
, 0, release_buffer
, context
, 0);
92 if (!context
|| !buffer
) {
94 return AVERROR(ENOMEM
);
98 pic
->data
[0] = (void *)1;
102 static inline void set_context(AVCodecContext
*avctx
)
104 VDADecoderContext
*ctx
= avctx
->priv_data
;
105 ctx
->hwaccel_context
= avctx
->hwaccel_context
;
106 avctx
->hwaccel_context
= &ctx
->vda_ctx
;
107 ctx
->get_format
= avctx
->get_format
;
108 avctx
->get_format
= get_format
;
109 ctx
->get_buffer2
= avctx
->get_buffer2
;
110 avctx
->get_buffer2
= get_buffer2
;
111 #if FF_API_GET_BUFFER
112 ctx
->get_buffer
= avctx
->get_buffer
;
113 avctx
->get_buffer
= NULL
;
117 static inline void restore_context(AVCodecContext
*avctx
)
119 VDADecoderContext
*ctx
= avctx
->priv_data
;
120 avctx
->hwaccel_context
= ctx
->hwaccel_context
;
121 avctx
->get_format
= ctx
->get_format
;
122 avctx
->get_buffer2
= ctx
->get_buffer2
;
123 #if FF_API_GET_BUFFER
124 avctx
->get_buffer
= ctx
->get_buffer
;
128 static int vdadec_decode(AVCodecContext
*avctx
,
129 void *data
, int *got_frame
, AVPacket
*avpkt
)
131 VDADecoderContext
*ctx
= avctx
->priv_data
;
136 ret
= ff_h264_decoder
.decode(avctx
, data
, got_frame
, avpkt
);
137 restore_context(avctx
);
139 AVBufferRef
*buffer
= pic
->buf
[0];
140 VDABufferContext
*context
= av_buffer_get_opaque(buffer
);
141 CVPixelBufferRef cv_buffer
= (CVPixelBufferRef
)pic
->data
[3];
143 CVPixelBufferRetain(cv_buffer
);
144 CVPixelBufferLockBaseAddress(cv_buffer
, 0);
145 context
->cv_buffer
= cv_buffer
;
146 pic
->format
= ctx
->pix_fmt
;
147 if (CVPixelBufferIsPlanar(cv_buffer
)) {
148 int i
, count
= CVPixelBufferGetPlaneCount(cv_buffer
);
149 av_assert0(count
< 4);
150 for (i
= 0; i
< count
; i
++) {
151 pic
->data
[i
] = CVPixelBufferGetBaseAddressOfPlane(cv_buffer
, i
);
152 pic
->linesize
[i
] = CVPixelBufferGetBytesPerRowOfPlane(cv_buffer
, i
);
155 pic
->data
[0] = CVPixelBufferGetBaseAddress(cv_buffer
);
156 pic
->linesize
[0] = CVPixelBufferGetBytesPerRow(cv_buffer
);
159 avctx
->pix_fmt
= ctx
->pix_fmt
;
164 static av_cold
int vdadec_close(AVCodecContext
*avctx
)
166 VDADecoderContext
*ctx
= avctx
->priv_data
;
167 /* release buffers and decoder */
168 ff_vda_destroy_decoder(&ctx
->vda_ctx
);
169 /* close H.264 decoder */
170 if (ctx
->h264_initialized
) {
172 ff_h264_decoder
.close(avctx
);
173 restore_context(avctx
);
178 static av_cold
int vdadec_init(AVCodecContext
*avctx
)
180 VDADecoderContext
*ctx
= avctx
->priv_data
;
181 struct vda_context
*vda_ctx
= &ctx
->vda_ctx
;
185 ctx
->h264_initialized
= 0;
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
;
192 ff_h264_vda_decoder
.pix_fmts
= vda_pixfmts
;
196 memset(vda_ctx
, 0, sizeof(struct vda_context
));
197 vda_ctx
->width
= avctx
->width
;
198 vda_ctx
->height
= avctx
->height
;
199 vda_ctx
->format
= 'avc1';
200 vda_ctx
->use_sync_decoding
= 1;
201 vda_ctx
->use_ref_buffer
= 1;
202 ctx
->pix_fmt
= avctx
->get_format(avctx
, avctx
->codec
->pix_fmts
);
203 switch (ctx
->pix_fmt
) {
204 case AV_PIX_FMT_UYVY422
:
205 vda_ctx
->cv_pix_fmt_type
= '2vuy';
207 case AV_PIX_FMT_YUYV422
:
208 vda_ctx
->cv_pix_fmt_type
= 'yuvs';
210 case AV_PIX_FMT_NV12
:
211 vda_ctx
->cv_pix_fmt_type
= '420v';
213 case AV_PIX_FMT_YUV420P
:
214 vda_ctx
->cv_pix_fmt_type
= 'y420';
217 av_log(avctx
, AV_LOG_ERROR
, "Unsupported pixel format: %d\n", avctx
->pix_fmt
);
220 status
= ff_vda_create_decoder(vda_ctx
,
221 avctx
->extradata
, avctx
->extradata_size
);
222 if (status
!= kVDADecoderNoErr
) {
223 av_log(avctx
, AV_LOG_ERROR
,
224 "Failed to init VDA decoder: %d.\n", status
);
228 /* init H.264 decoder */
230 ret
= ff_h264_decoder
.init(avctx
);
231 restore_context(avctx
);
233 av_log(avctx
, AV_LOG_ERROR
, "Failed to open H.264 decoder.\n");
236 ctx
->h264_initialized
= 1;
238 for (i
= 0; i
< MAX_SPS_COUNT
; i
++) {
239 SPS
*sps
= ctx
->h264ctx
.sps_buffers
[i
];
240 if (sps
&& (sps
->bit_depth_luma
!= 8 ||
241 sps
->chroma_format_idc
== 2 ||
242 sps
->chroma_format_idc
== 3)) {
243 av_log(avctx
, AV_LOG_ERROR
, "Format is not supported.\n");
255 static void vdadec_flush(AVCodecContext
*avctx
)
258 ff_h264_decoder
.flush(avctx
);
259 restore_context(avctx
);
262 AVCodec ff_h264_vda_decoder
= {
264 .type
= AVMEDIA_TYPE_VIDEO
,
265 .id
= AV_CODEC_ID_H264
,
266 .priv_data_size
= sizeof(VDADecoderContext
),
268 .close
= vdadec_close
,
269 .decode
= vdadec_decode
,
270 .capabilities
= CODEC_CAP_DELAY
,
271 .flush
= vdadec_flush
,
272 .long_name
= NULL_IF_CONFIG_SMALL("H.264 (VDA acceleration)"),