mmaldec: be more tolerant against MMAL not returning decoded output
[ffmpeg.git] / libavcodec / vda_h264.c
1 /*
2  * VDA H.264 hardware acceleration
3  *
4  * copyright (c) 2011 Sebastien Zwickert
5  *
6  * This file is part of Libav.
7  *
8  * Libav 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  * Libav 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 Libav; 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/CFNumber.h>
24 #include <CoreFoundation/CFData.h>
25 #include <CoreFoundation/CFString.h>
26
27 #include "libavutil/avutil.h"
28 #include "h264.h"
29 #include "internal.h"
30 #include "vda.h"
31 #include "vda_internal.h"
32
33 typedef struct VDAContext {
34     // The current bitstream buffer.
35     uint8_t             *bitstream;
36
37     // The current size of the bitstream.
38     int                  bitstream_size;
39
40     // The reference size used for fast reallocation.
41     int                  allocated_size;
42
43     CVImageBufferRef frame;
44 } VDAContext;
45
46 /* Decoder callback that adds the VDA frame to the queue in display order. */
47 static void vda_decoder_callback(void *vda_hw_ctx,
48                                  CFDictionaryRef user_info,
49                                  OSStatus status,
50                                  uint32_t infoFlags,
51                                  CVImageBufferRef image_buffer)
52 {
53     struct vda_context *vda_ctx = vda_hw_ctx;
54
55     if (!image_buffer)
56         return;
57
58     if (vda_ctx->cv_pix_fmt_type != CVPixelBufferGetPixelFormatType(image_buffer))
59         return;
60
61     vda_ctx->cv_buffer = CVPixelBufferRetain(image_buffer);
62 }
63
64 static int vda_sync_decode(VDAContext *ctx, struct vda_context *vda_ctx)
65 {
66     OSStatus status;
67     CFDataRef coded_frame;
68     uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames
69
70     coded_frame = CFDataCreate(kCFAllocatorDefault,
71                                ctx->bitstream,
72                                ctx->bitstream_size);
73
74     status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, NULL);
75
76     if (kVDADecoderNoErr == status)
77         status = VDADecoderFlush(vda_ctx->decoder, flush_flags);
78
79     CFRelease(coded_frame);
80
81     return status;
82 }
83
84
85 static int vda_old_h264_start_frame(AVCodecContext *avctx,
86                                 av_unused const uint8_t *buffer,
87                                 av_unused uint32_t size)
88 {
89     VDAContext *vda = avctx->internal->hwaccel_priv_data;
90     struct vda_context *vda_ctx         = avctx->hwaccel_context;
91
92     if (!vda_ctx->decoder)
93         return -1;
94
95     vda->bitstream_size = 0;
96
97     return 0;
98 }
99
100 static int vda_old_h264_decode_slice(AVCodecContext *avctx,
101                                  const uint8_t *buffer,
102                                  uint32_t size)
103 {
104     VDAContext *vda                     = avctx->internal->hwaccel_priv_data;
105     struct vda_context *vda_ctx         = avctx->hwaccel_context;
106     void *tmp;
107
108     if (!vda_ctx->decoder)
109         return -1;
110
111     tmp = av_fast_realloc(vda->bitstream,
112                           &vda->allocated_size,
113                           vda->bitstream_size + size + 4);
114     if (!tmp)
115         return AVERROR(ENOMEM);
116
117     vda->bitstream = tmp;
118
119     AV_WB32(vda->bitstream + vda->bitstream_size, size);
120     memcpy(vda->bitstream + vda->bitstream_size + 4, buffer, size);
121
122     vda->bitstream_size += size + 4;
123
124     return 0;
125 }
126
127 static int vda_old_h264_end_frame(AVCodecContext *avctx)
128 {
129     H264Context *h                      = avctx->priv_data;
130     VDAContext *vda                     = avctx->internal->hwaccel_priv_data;
131     struct vda_context *vda_ctx         = avctx->hwaccel_context;
132     AVFrame *frame                      = h->cur_pic_ptr->f;
133     int status;
134
135     if (!vda_ctx->decoder || !vda->bitstream)
136         return -1;
137
138     status = vda_sync_decode(vda, vda_ctx);
139     frame->data[3] = (void*)vda_ctx->cv_buffer;
140
141     if (status)
142         av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
143
144     return status;
145 }
146
147 int ff_vda_create_decoder(struct vda_context *vda_ctx,
148                           uint8_t *extradata,
149                           int extradata_size)
150 {
151     OSStatus status = kVDADecoderNoErr;
152     CFNumberRef height;
153     CFNumberRef width;
154     CFNumberRef format;
155     CFDataRef avc_data;
156     CFMutableDictionaryRef config_info;
157     CFMutableDictionaryRef buffer_attributes;
158     CFMutableDictionaryRef io_surface_properties;
159     CFNumberRef cv_pix_fmt;
160
161     /* Each VCL NAL in the bistream sent to the decoder
162      * is preceded by a 4 bytes length header.
163      * Change the avcC atom header if needed, to signal headers of 4 bytes. */
164     if (extradata_size >= 4 && (extradata[4] & 0x03) != 0x03) {
165         uint8_t *rw_extradata;
166
167         if (!(rw_extradata = av_malloc(extradata_size)))
168             return AVERROR(ENOMEM);
169
170         memcpy(rw_extradata, extradata, extradata_size);
171
172         rw_extradata[4] |= 0x03;
173
174         avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, extradata_size);
175
176         av_freep(&rw_extradata);
177     } else {
178         avc_data = CFDataCreate(kCFAllocatorDefault, extradata, extradata_size);
179     }
180
181     config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
182                                             4,
183                                             &kCFTypeDictionaryKeyCallBacks,
184                                             &kCFTypeDictionaryValueCallBacks);
185
186     height   = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->height);
187     width    = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->width);
188     format   = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->format);
189
190     CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height);
191     CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width);
192     CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format);
193     CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data);
194
195     buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
196                                                   2,
197                                                   &kCFTypeDictionaryKeyCallBacks,
198                                                   &kCFTypeDictionaryValueCallBacks);
199     io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
200                                                       0,
201                                                       &kCFTypeDictionaryKeyCallBacks,
202                                                       &kCFTypeDictionaryValueCallBacks);
203     cv_pix_fmt      = CFNumberCreate(kCFAllocatorDefault,
204                                      kCFNumberSInt32Type,
205                                      &vda_ctx->cv_pix_fmt_type);
206     CFDictionarySetValue(buffer_attributes,
207                          kCVPixelBufferPixelFormatTypeKey,
208                          cv_pix_fmt);
209     CFDictionarySetValue(buffer_attributes,
210                          kCVPixelBufferIOSurfacePropertiesKey,
211                          io_surface_properties);
212
213     status = VDADecoderCreate(config_info,
214                               buffer_attributes,
215                               (VDADecoderOutputCallback *)vda_decoder_callback,
216                               vda_ctx,
217                               &vda_ctx->decoder);
218
219     CFRelease(height);
220     CFRelease(width);
221     CFRelease(format);
222     CFRelease(avc_data);
223     CFRelease(config_info);
224     CFRelease(io_surface_properties);
225     CFRelease(cv_pix_fmt);
226     CFRelease(buffer_attributes);
227
228     return status;
229 }
230
231 int ff_vda_destroy_decoder(struct vda_context *vda_ctx)
232 {
233     OSStatus status = kVDADecoderNoErr;
234
235     if (vda_ctx->decoder)
236         status = VDADecoderDestroy(vda_ctx->decoder);
237
238     return status;
239 }
240
241 static int vda_h264_uninit(AVCodecContext *avctx)
242 {
243     VDAContext *vda = avctx->internal->hwaccel_priv_data;
244     av_freep(&vda->bitstream);
245     if (vda->frame)
246         CVPixelBufferRelease(vda->frame);
247     return 0;
248 }
249
250 AVHWAccel ff_h264_vda_old_hwaccel = {
251     .name           = "h264_vda",
252     .type           = AVMEDIA_TYPE_VIDEO,
253     .id             = AV_CODEC_ID_H264,
254     .pix_fmt        = AV_PIX_FMT_VDA_VLD,
255     .start_frame    = vda_old_h264_start_frame,
256     .decode_slice   = vda_old_h264_decode_slice,
257     .end_frame      = vda_old_h264_end_frame,
258     .uninit         = vda_h264_uninit,
259     .priv_data_size = sizeof(VDAContext),
260 };
261
262 void ff_vda_output_callback(void *opaque,
263                             CFDictionaryRef user_info,
264                             OSStatus status,
265                             uint32_t infoFlags,
266                             CVImageBufferRef image_buffer)
267 {
268     AVCodecContext *ctx = opaque;
269     VDAContext *vda = ctx->internal->hwaccel_priv_data;
270
271
272     if (vda->frame) {
273         CVPixelBufferRelease(vda->frame);
274         vda->frame = NULL;
275     }
276
277     if (!image_buffer)
278         return;
279
280     vda->frame = CVPixelBufferRetain(image_buffer);
281 }
282
283 static int vda_h264_start_frame(AVCodecContext *avctx,
284                                 const uint8_t *buffer,
285                                 uint32_t size)
286 {
287     VDAContext *vda = avctx->internal->hwaccel_priv_data;
288
289     vda->bitstream_size = 0;
290
291     return 0;
292 }
293
294 static int vda_h264_decode_slice(AVCodecContext *avctx,
295                                  const uint8_t *buffer,
296                                  uint32_t size)
297 {
298     VDAContext *vda       = avctx->internal->hwaccel_priv_data;
299     void *tmp;
300
301     tmp = av_fast_realloc(vda->bitstream,
302                           &vda->allocated_size,
303                           vda->bitstream_size + size + 4);
304     if (!tmp)
305         return AVERROR(ENOMEM);
306
307     vda->bitstream = tmp;
308
309     AV_WB32(vda->bitstream + vda->bitstream_size, size);
310     memcpy(vda->bitstream + vda->bitstream_size + 4, buffer, size);
311
312     vda->bitstream_size += size + 4;
313
314     return 0;
315 }
316
317 static void release_buffer(void *opaque, uint8_t *data)
318 {
319     CVImageBufferRef frame = (CVImageBufferRef)data;
320     CVPixelBufferRelease(frame);
321 }
322
323 static int vda_h264_end_frame(AVCodecContext *avctx)
324 {
325     H264Context *h        = avctx->priv_data;
326     VDAContext *vda       = avctx->internal->hwaccel_priv_data;
327     AVVDAContext *vda_ctx = avctx->hwaccel_context;
328     AVFrame *frame        = h->cur_pic_ptr->f;
329     uint32_t flush_flags  = 1 << 0; ///< kVDADecoderFlush_emitFrames
330     CFDataRef coded_frame;
331     OSStatus status;
332
333     if (!vda->bitstream_size)
334         return AVERROR_INVALIDDATA;
335
336
337     coded_frame = CFDataCreate(kCFAllocatorDefault,
338                                vda->bitstream,
339                                vda->bitstream_size);
340
341     status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, NULL);
342
343     if (status == kVDADecoderNoErr)
344         status = VDADecoderFlush(vda_ctx->decoder, flush_flags);
345
346     CFRelease(coded_frame);
347
348     if (!vda->frame)
349         return AVERROR_UNKNOWN;
350
351     if (status != kVDADecoderNoErr) {
352         av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
353         return AVERROR_UNKNOWN;
354     }
355
356     av_buffer_unref(&frame->buf[0]);
357
358     frame->buf[0] = av_buffer_create((uint8_t*)vda->frame,
359                                      sizeof(vda->frame),
360                                      release_buffer, NULL,
361                                      AV_BUFFER_FLAG_READONLY);
362     if (!frame->buf[0])
363         return AVERROR(ENOMEM);
364
365     frame->data[3] = (uint8_t*)vda->frame;
366     vda->frame = NULL;
367
368     return 0;
369 }
370
371 int ff_vda_default_init(AVCodecContext *avctx)
372 {
373     AVVDAContext *vda_ctx = avctx->hwaccel_context;
374     OSStatus status = kVDADecoderNoErr;
375     CFNumberRef height;
376     CFNumberRef width;
377     CFNumberRef format;
378     CFDataRef avc_data;
379     CFMutableDictionaryRef config_info;
380     CFMutableDictionaryRef buffer_attributes;
381     CFMutableDictionaryRef io_surface_properties;
382     CFNumberRef cv_pix_fmt;
383     int32_t fmt = 'avc1', pix_fmt = vda_ctx->cv_pix_fmt_type;
384
385     // kCVPixelFormatType_420YpCbCr8Planar;
386
387     /* Each VCL NAL in the bistream sent to the decoder
388      * is preceded by a 4 bytes length header.
389      * Change the avcC atom header if needed, to signal headers of 4 bytes. */
390     if (avctx->extradata_size >= 4 && (avctx->extradata[4] & 0x03) != 0x03) {
391         uint8_t *rw_extradata;
392
393         if (!(rw_extradata = av_malloc(avctx->extradata_size)))
394             return AVERROR(ENOMEM);
395
396         memcpy(rw_extradata, avctx->extradata, avctx->extradata_size);
397
398         rw_extradata[4] |= 0x03;
399
400         avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, avctx->extradata_size);
401
402         av_freep(&rw_extradata);
403     } else {
404         avc_data = CFDataCreate(kCFAllocatorDefault,
405                                 avctx->extradata, avctx->extradata_size);
406     }
407
408     config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
409                                             4,
410                                             &kCFTypeDictionaryKeyCallBacks,
411                                             &kCFTypeDictionaryValueCallBacks);
412
413     height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->height);
414     width  = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->width);
415     format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &fmt);
416     CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height);
417     CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width);
418     CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data);
419     CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format);
420
421     buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
422                                                   2,
423                                                   &kCFTypeDictionaryKeyCallBacks,
424                                                   &kCFTypeDictionaryValueCallBacks);
425     io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
426                                                       0,
427                                                       &kCFTypeDictionaryKeyCallBacks,
428                                                       &kCFTypeDictionaryValueCallBacks);
429     cv_pix_fmt      = CFNumberCreate(kCFAllocatorDefault,
430                                      kCFNumberSInt32Type,
431                                      &pix_fmt);
432
433     CFDictionarySetValue(buffer_attributes,
434                          kCVPixelBufferPixelFormatTypeKey,
435                          cv_pix_fmt);
436     CFDictionarySetValue(buffer_attributes,
437                          kCVPixelBufferIOSurfacePropertiesKey,
438                          io_surface_properties);
439
440     status = VDADecoderCreate(config_info,
441                               buffer_attributes,
442                               (VDADecoderOutputCallback *)ff_vda_output_callback,
443                               avctx,
444                               &vda_ctx->decoder);
445
446     CFRelease(format);
447     CFRelease(height);
448     CFRelease(width);
449     CFRelease(avc_data);
450     CFRelease(config_info);
451     CFRelease(cv_pix_fmt);
452     CFRelease(io_surface_properties);
453     CFRelease(buffer_attributes);
454
455     if (status != kVDADecoderNoErr) {
456         av_log(avctx, AV_LOG_ERROR, "Cannot initialize VDA %d\n", status);
457     }
458
459     switch (status) {
460     case kVDADecoderHardwareNotSupportedErr:
461     case kVDADecoderFormatNotSupportedErr:
462         return AVERROR(ENOSYS);
463     case kVDADecoderConfigurationError:
464         return AVERROR(EINVAL);
465     case kVDADecoderDecoderFailedErr:
466         return AVERROR_INVALIDDATA;
467     case kVDADecoderNoErr:
468         return 0;
469     default:
470         return AVERROR_UNKNOWN;
471     }
472 }
473
474 static int vda_h264_alloc_frame(AVCodecContext *avctx, AVFrame *frame)
475 {
476     frame->width  = avctx->width;
477     frame->height = avctx->height;
478     frame->format = avctx->pix_fmt;
479     frame->buf[0] = av_buffer_alloc(1);
480
481     if (!frame->buf[0])
482         return AVERROR(ENOMEM);
483     return 0;
484 }
485
486 AVHWAccel ff_h264_vda_hwaccel = {
487     .name           = "h264_vda",
488     .type           = AVMEDIA_TYPE_VIDEO,
489     .id             = AV_CODEC_ID_H264,
490     .pix_fmt        = AV_PIX_FMT_VDA,
491     .alloc_frame    = vda_h264_alloc_frame,
492     .start_frame    = vda_h264_start_frame,
493     .decode_slice   = vda_h264_decode_slice,
494     .end_frame      = vda_h264_end_frame,
495     .uninit         = vda_h264_uninit,
496     .priv_data_size = sizeof(VDAContext),
497 };