#include "h264.h"
#include "vda.h"
-#if FF_API_VDA_ASYNC
-#include <CoreFoundation/CFDictionary.h>
-
-/* helper to create a dictionary according to the given pts */
-static CFDictionaryRef vda_dictionary_with_pts(int64_t i_pts)
-{
- CFStringRef key = CFSTR("FF_VDA_DECODER_PTS_KEY");
- CFNumberRef value = CFNumberCreate(kCFAllocatorDefault,
- kCFNumberSInt64Type, &i_pts);
- CFDictionaryRef user_info = CFDictionaryCreate(kCFAllocatorDefault,
- (const void **)&key,
- (const void **)&value,
- 1,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CFRelease(value);
- return user_info;
-}
-
-/* helper to retrieve the pts from the given dictionary */
-static int64_t vda_pts_from_dictionary(CFDictionaryRef user_info)
-{
- CFNumberRef pts;
- int64_t outValue = 0;
-
- if (!user_info)
- return 0;
-
- pts = CFDictionaryGetValue(user_info, CFSTR("FF_VDA_DECODER_PTS_KEY"));
-
- if (pts)
- CFNumberGetValue(pts, kCFNumberSInt64Type, &outValue);
-
- return outValue;
-}
-
-/* Remove and release all frames from the queue. */
-static void vda_clear_queue(struct vda_context *vda_ctx)
-{
- vda_frame *top_frame;
-
- pthread_mutex_lock(&vda_ctx->queue_mutex);
-
- while (vda_ctx->queue) {
- top_frame = vda_ctx->queue;
- vda_ctx->queue = top_frame->next_frame;
- ff_vda_release_vda_frame(top_frame);
- }
-
- pthread_mutex_unlock(&vda_ctx->queue_mutex);
-}
-
-static int vda_decoder_decode(struct vda_context *vda_ctx,
- uint8_t *bitstream,
- int bitstream_size,
- int64_t frame_pts)
-{
- OSStatus status = kVDADecoderNoErr;
- CFDictionaryRef user_info;
- CFDataRef coded_frame;
-
- coded_frame = CFDataCreate(kCFAllocatorDefault, bitstream, bitstream_size);
- user_info = vda_dictionary_with_pts(frame_pts);
- status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, user_info);
-
- CFRelease(user_info);
- CFRelease(coded_frame);
-
- return status;
-}
-
-vda_frame *ff_vda_queue_pop(struct vda_context *vda_ctx)
-{
- vda_frame *top_frame;
-
- if (!vda_ctx->queue)
- return NULL;
-
- pthread_mutex_lock(&vda_ctx->queue_mutex);
- top_frame = vda_ctx->queue;
- vda_ctx->queue = top_frame->next_frame;
- pthread_mutex_unlock(&vda_ctx->queue_mutex);
-
- return top_frame;
-}
-
-void ff_vda_release_vda_frame(vda_frame *frame)
-{
- if (frame) {
- CVPixelBufferRelease(frame->cv_buffer);
- av_freep(&frame);
- }
-}
-#endif
-
/* Decoder callback that adds the VDA frame to the queue in display order. */
static void vda_decoder_callback(void *vda_hw_ctx,
CFDictionaryRef user_info,
if (vda_ctx->cv_pix_fmt_type != CVPixelBufferGetPixelFormatType(image_buffer))
return;
- if (vda_ctx->use_sync_decoding) {
- vda_ctx->cv_buffer = CVPixelBufferRetain(image_buffer);
- } else {
- vda_frame *new_frame;
- vda_frame *queue_walker;
-
- if (!(new_frame = av_mallocz(sizeof(*new_frame))))
- return;
- new_frame->next_frame = NULL;
- new_frame->cv_buffer = CVPixelBufferRetain(image_buffer);
- new_frame->pts = vda_pts_from_dictionary(user_info);
-
- pthread_mutex_lock(&vda_ctx->queue_mutex);
-
- queue_walker = vda_ctx->queue;
-
- if (!queue_walker || new_frame->pts < queue_walker->pts) {
- /* we have an empty queue, or this frame earlier than the current queue head */
- new_frame->next_frame = queue_walker;
- vda_ctx->queue = new_frame;
- } else {
- /* walk the queue and insert this frame where it belongs in display order */
- vda_frame *next_frame;
- while (1) {
- next_frame = queue_walker->next_frame;
- if (!next_frame || new_frame->pts < next_frame->pts) {
- new_frame->next_frame = next_frame;
- queue_walker->next_frame = new_frame;
- break;
- }
- queue_walker = next_frame;
- }
- }
-
- pthread_mutex_unlock(&vda_ctx->queue_mutex);
- }
+ vda_ctx->cv_buffer = CVPixelBufferRetain(image_buffer);
}
static int vda_sync_decode(struct vda_context *vda_ctx)
}
-static int start_frame(AVCodecContext *avctx,
- av_unused const uint8_t *buffer,
- av_unused uint32_t size)
+static int vda_h264_start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
{
struct vda_context *vda_ctx = avctx->hwaccel_context;
return 0;
}
-static int decode_slice(AVCodecContext *avctx,
- const uint8_t *buffer,
- uint32_t size)
+static int vda_h264_decode_slice(AVCodecContext *avctx,
+ const uint8_t *buffer,
+ uint32_t size)
{
struct vda_context *vda_ctx = avctx->hwaccel_context;
void *tmp;
return 0;
}
-static int end_frame(AVCodecContext *avctx)
+static int vda_h264_end_frame(AVCodecContext *avctx)
{
H264Context *h = avctx->priv_data;
struct vda_context *vda_ctx = avctx->hwaccel_context;
if (!vda_ctx->decoder || !vda_ctx->priv_bitstream)
return -1;
- if (vda_ctx->use_sync_decoding) {
- status = vda_sync_decode(vda_ctx);
- frame->data[3] = (void*)vda_ctx->cv_buffer;
- } else {
- status = vda_decoder_decode(vda_ctx, vda_ctx->priv_bitstream,
- vda_ctx->priv_bitstream_size,
- frame->reordered_opaque);
- }
+ status = vda_sync_decode(vda_ctx);
+ frame->data[3] = (void*)vda_ctx->cv_buffer;
if (status)
av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
CFMutableDictionaryRef io_surface_properties;
CFNumberRef cv_pix_fmt;
-#if FF_API_VDA_ASYNC
- pthread_mutex_init(&vda_ctx->queue_mutex, NULL);
-#endif
-
/* Each VCL NAL in the bistream sent to the decoder
* is preceded by a 4 bytes length header.
* Change the avcC atom header if needed, to signal headers of 4 bytes. */
if (vda_ctx->decoder)
status = VDADecoderDestroy(vda_ctx->decoder);
-#if FF_API_VDA_ASYNC
- vda_clear_queue(vda_ctx);
- pthread_mutex_destroy(&vda_ctx->queue_mutex);
-#endif
-
av_freep(&vda_ctx->priv_bitstream);
return status;
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_H264,
.pix_fmt = AV_PIX_FMT_VDA_VLD,
- .start_frame = start_frame,
- .decode_slice = decode_slice,
- .end_frame = end_frame,
+ .start_frame = vda_h264_start_frame,
+ .decode_slice = vda_h264_decode_slice,
+ .end_frame = vda_h264_end_frame,
};