vda_h264.c
Go to the documentation of this file.
1 /*
2  * VDA H264 HW acceleration.
3  *
4  * copyright (c) 2011 Sebastien Zwickert
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 <CoreFoundation/CFDictionary.h>
24 #include <CoreFoundation/CFNumber.h>
25 #include <CoreFoundation/CFData.h>
26 
27 #include "vda.h"
28 #include "libavutil/avutil.h"
29 #include "h264.h"
30 
31 
32 /* Decoder callback that adds the vda frame to the queue in display order. */
33 static void vda_decoder_callback (void *vda_hw_ctx,
34  CFDictionaryRef user_info,
35  OSStatus status,
36  uint32_t infoFlags,
37  CVImageBufferRef image_buffer)
38 {
39  struct vda_context *vda_ctx = vda_hw_ctx;
40 
41  if (!image_buffer)
42  return;
43 
44  if (vda_ctx->cv_pix_fmt_type != CVPixelBufferGetPixelFormatType(image_buffer))
45  return;
46 
47  vda_ctx->cv_buffer = CVPixelBufferRetain(image_buffer);
48 }
49 
50 static int vda_sync_decode(struct vda_context *vda_ctx)
51 {
52  OSStatus status;
53  CFDataRef coded_frame;
54  uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames
55 
56  coded_frame = CFDataCreate(kCFAllocatorDefault,
57  vda_ctx->priv_bitstream,
58  vda_ctx->priv_bitstream_size);
59 
60  status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, NULL);
61 
62  if (kVDADecoderNoErr == status)
63  status = VDADecoderFlush(vda_ctx->decoder, flush_flags);
64 
65  CFRelease(coded_frame);
66 
67  return status;
68 }
69 
70 
72  av_unused const uint8_t *buffer,
73  av_unused uint32_t size)
74 {
75  struct vda_context *vda_ctx = avctx->hwaccel_context;
76 
77  if (!vda_ctx->decoder)
78  return -1;
79 
80  vda_ctx->priv_bitstream_size = 0;
81 
82  return 0;
83 }
84 
86  const uint8_t *buffer,
87  uint32_t size)
88 {
89  struct vda_context *vda_ctx = avctx->hwaccel_context;
90  void *tmp;
91 
92  if (!vda_ctx->decoder)
93  return -1;
94 
95  tmp = av_fast_realloc(vda_ctx->priv_bitstream,
96  &vda_ctx->priv_allocated_size,
97  vda_ctx->priv_bitstream_size + size + 4);
98  if (!tmp)
99  return AVERROR(ENOMEM);
100 
101  vda_ctx->priv_bitstream = tmp;
102 
103  AV_WB32(vda_ctx->priv_bitstream + vda_ctx->priv_bitstream_size, size);
104  memcpy(vda_ctx->priv_bitstream + vda_ctx->priv_bitstream_size + 4, buffer, size);
105 
106  vda_ctx->priv_bitstream_size += size + 4;
107 
108  return 0;
109 }
110 
112 {
113  H264Context *h = avctx->priv_data;
114  struct vda_context *vda_ctx = avctx->hwaccel_context;
115  AVFrame *frame = &h->cur_pic_ptr->f;
116  int status;
117 
118  if (!vda_ctx->decoder || !vda_ctx->priv_bitstream)
119  return -1;
120 
121  status = vda_sync_decode(vda_ctx);
122  frame->data[3] = (void*)vda_ctx->cv_buffer;
123 
124  if (status)
125  av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
126 
127  return status;
128 }
129 
130 int ff_vda_create_decoder(struct vda_context *vda_ctx,
131  uint8_t *extradata,
132  int extradata_size)
133 {
134  OSStatus status;
135  CFNumberRef height;
136  CFNumberRef width;
137  CFNumberRef format;
138  CFDataRef avc_data;
139  CFMutableDictionaryRef config_info;
140  CFMutableDictionaryRef buffer_attributes;
141  CFMutableDictionaryRef io_surface_properties;
142  CFNumberRef cv_pix_fmt;
143 
144  vda_ctx->priv_bitstream = NULL;
145  vda_ctx->priv_allocated_size = 0;
146 
147  /* Each VCL NAL in the bitstream sent to the decoder
148  * is preceded by a 4 bytes length header.
149  * Change the avcC atom header if needed, to signal headers of 4 bytes. */
150  if (extradata_size >= 4 && (extradata[4] & 0x03) != 0x03) {
151  uint8_t *rw_extradata;
152 
153  if (!(rw_extradata = av_malloc(extradata_size)))
154  return AVERROR(ENOMEM);
155 
156  memcpy(rw_extradata, extradata, extradata_size);
157 
158  rw_extradata[4] |= 0x03;
159 
160  avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, extradata_size);
161 
162  av_freep(&rw_extradata);
163  } else {
164  avc_data = CFDataCreate(kCFAllocatorDefault, extradata, extradata_size);
165  }
166 
167  config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
168  4,
169  &kCFTypeDictionaryKeyCallBacks,
170  &kCFTypeDictionaryValueCallBacks);
171 
172  height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->height);
173  width = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->width);
174  format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->format);
175 
176  CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height);
177  CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width);
178  CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format);
179  CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data);
180 
181  buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
182  2,
183  &kCFTypeDictionaryKeyCallBacks,
184  &kCFTypeDictionaryValueCallBacks);
185  io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
186  0,
187  &kCFTypeDictionaryKeyCallBacks,
188  &kCFTypeDictionaryValueCallBacks);
189  cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault,
190  kCFNumberSInt32Type,
191  &vda_ctx->cv_pix_fmt_type);
192  CFDictionarySetValue(buffer_attributes,
193  kCVPixelBufferPixelFormatTypeKey,
194  cv_pix_fmt);
195  CFDictionarySetValue(buffer_attributes,
196  kCVPixelBufferIOSurfacePropertiesKey,
197  io_surface_properties);
198 
199  status = VDADecoderCreate(config_info,
200  buffer_attributes,
202  vda_ctx,
203  &vda_ctx->decoder);
204 
205  CFRelease(height);
206  CFRelease(width);
207  CFRelease(format);
208  CFRelease(avc_data);
209  CFRelease(config_info);
210  CFRelease(io_surface_properties);
211  CFRelease(cv_pix_fmt);
212  CFRelease(buffer_attributes);
213 
214  return status;
215 }
216 
218 {
219  OSStatus status = kVDADecoderNoErr;
220 
221  if (vda_ctx->decoder)
222  status = VDADecoderDestroy(vda_ctx->decoder);
223 
224  av_freep(&vda_ctx->priv_bitstream);
225 
226  return status;
227 }
228 
230  .name = "h264_vda",
231  .type = AVMEDIA_TYPE_VIDEO,
232  .id = AV_CODEC_ID_H264,
233  .pix_fmt = AV_PIX_FMT_VDA_VLD,
234  .start_frame = vda_h264_start_frame,
235  .decode_slice = vda_h264_decode_slice,
236  .end_frame = vda_h264_end_frame,
237 };
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
static int vda_sync_decode(struct vda_context *vda_ctx)
Definition: vda_h264.c:50
static int vda_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
Definition: vda_h264.c:85
external API header
H264Context.
Definition: h264.h:260
int format
The frame format.
Definition: vda.h:104
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
initialize output if(nPeaks >3)%at least 3 peaks in spectrum for trying to find f0 nf0peaks
#define AV_WB32(p, darg)
Definition: intreadwrite.h:265
OSType cv_pix_fmt_type
The pixel format for output image buffers.
Definition: vda.h:112
uint8_t
void * hwaccel_context
Hardware accelerator context.
int width
The frame width.
Definition: vda.h:88
CVPixelBufferRef cv_buffer
The Core Video pixel buffer that contains the current image data.
Definition: vda.h:72
frame
Definition: stft.m:14
H.264 / AVC / MPEG4 part10 codec.
static int vda_h264_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size)
Definition: vda_h264.c:71
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given block if it is not large enough, otherwise do nothing.
VDADecoder decoder
VDA decoder object.
Definition: vda.h:64
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
This structure is used to provide the necessary configurations and data to the VDA FFmpeg HWAccel imp...
Definition: vda.h:57
int size
const char * name
Name of the hardware accelerated codec.
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 format(the sample packing is implied by the sample format) and sample rate.The lists are not just lists
NULL
Definition: eval.c:55
static int width
Definition: tests/utils.c:158
AVHWAccel.
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.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
static void vda_decoder_callback(void *vda_hw_ctx, CFDictionaryRef user_info, OSStatus status, uint32_t infoFlags, CVImageBufferRef image_buffer)
Definition: vda_h264.c:33
BYTE int const BYTE int int int height
Definition: avisynth_c.h:713
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
AVHWAccel ff_h264_vda_hwaccel
Definition: vda_h264.c:229
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
uint8_t * priv_bitstream
The current bitstream buffer.
Definition: vda.h:120
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
hardware decoding through VDA
Definition: pixfmt.h:160
static int vda_h264_end_frame(AVCodecContext *avctx)
Definition: vda_h264.c:111
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
Picture * cur_pic_ptr
Definition: h264.h:273
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
struct AVFrame f
Definition: mpegvideo.h:98
int priv_allocated_size
The reference size used for fast reallocation.
Definition: vda.h:136
int height
The frame height.
Definition: vda.h:96
int priv_bitstream_size
The current size of the bitstream.
Definition: vda.h:128
#define av_unused
Definition: attributes.h:114