00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <pthread.h>
00024 #include <CoreFoundation/CFDictionary.h>
00025 #include <CoreFoundation/CFNumber.h>
00026 #include <CoreFoundation/CFData.h>
00027 #include <CoreFoundation/CFString.h>
00028
00029 #include "libavutil/avutil.h"
00030 #include "vda_internal.h"
00031
00032
00033 static CFDictionaryRef vda_dictionary_with_pts(int64_t i_pts)
00034 {
00035 CFStringRef key = CFSTR("FF_VDA_DECODER_PTS_KEY");
00036 CFNumberRef value = CFNumberCreate(kCFAllocatorDefault,
00037 kCFNumberSInt64Type, &i_pts);
00038 CFDictionaryRef user_info = CFDictionaryCreate(kCFAllocatorDefault,
00039 (const void **)&key,
00040 (const void **)&value,
00041 1,
00042 &kCFTypeDictionaryKeyCallBacks,
00043 &kCFTypeDictionaryValueCallBacks);
00044 CFRelease(value);
00045 return user_info;
00046 }
00047
00048
00049 static int64_t vda_pts_from_dictionary(CFDictionaryRef user_info)
00050 {
00051 CFNumberRef pts;
00052 int64_t outValue = 0;
00053
00054 if (!user_info)
00055 return 0;
00056
00057 pts = CFDictionaryGetValue(user_info, CFSTR("FF_VDA_DECODER_PTS_KEY"));
00058
00059 if (pts)
00060 CFNumberGetValue(pts, kCFNumberSInt64Type, &outValue);
00061
00062 return outValue;
00063 }
00064
00065
00066 static void vda_clear_queue(struct vda_context *vda_ctx)
00067 {
00068 vda_frame *top_frame;
00069
00070 pthread_mutex_lock(&vda_ctx->queue_mutex);
00071
00072 while (vda_ctx->queue) {
00073 top_frame = vda_ctx->queue;
00074 vda_ctx->queue = top_frame->next_frame;
00075 ff_vda_release_vda_frame(top_frame);
00076 }
00077
00078 pthread_mutex_unlock(&vda_ctx->queue_mutex);
00079 }
00080
00081
00082 static void vda_decoder_callback(void *vda_hw_ctx,
00083 CFDictionaryRef user_info,
00084 OSStatus status,
00085 uint32_t infoFlags,
00086 CVImageBufferRef image_buffer)
00087 {
00088 struct vda_context *vda_ctx = vda_hw_ctx;
00089 vda_frame *new_frame;
00090 vda_frame *queue_walker;
00091
00092 if (!image_buffer)
00093 return;
00094
00095 if (vda_ctx->cv_pix_fmt_type != CVPixelBufferGetPixelFormatType(image_buffer))
00096 return;
00097
00098 if (!(new_frame = av_mallocz(sizeof(vda_frame))))
00099 return;
00100 new_frame->next_frame = NULL;
00101 new_frame->cv_buffer = CVPixelBufferRetain(image_buffer);
00102 new_frame->pts = vda_pts_from_dictionary(user_info);
00103
00104 pthread_mutex_lock(&vda_ctx->queue_mutex);
00105
00106 queue_walker = vda_ctx->queue;
00107
00108 if (!queue_walker || new_frame->pts < queue_walker->pts) {
00109
00110 new_frame->next_frame = queue_walker;
00111 vda_ctx->queue = new_frame;
00112 } else {
00113
00114 vda_frame *next_frame;
00115 while (1) {
00116 next_frame = queue_walker->next_frame;
00117 if (!next_frame || new_frame->pts < next_frame->pts) {
00118 new_frame->next_frame = next_frame;
00119 queue_walker->next_frame = new_frame;
00120 break;
00121 }
00122 queue_walker = next_frame;
00123 }
00124 }
00125
00126 pthread_mutex_unlock(&vda_ctx->queue_mutex);
00127 }
00128
00129 int ff_vda_create_decoder(struct vda_context *vda_ctx,
00130 uint8_t *extradata,
00131 int extradata_size)
00132 {
00133 OSStatus status = kVDADecoderNoErr;
00134 CFNumberRef height;
00135 CFNumberRef width;
00136 CFNumberRef format;
00137 CFDataRef avc_data;
00138 CFMutableDictionaryRef config_info;
00139 CFMutableDictionaryRef buffer_attributes;
00140 CFMutableDictionaryRef io_surface_properties;
00141 CFNumberRef cv_pix_fmt;
00142
00143 pthread_mutex_init(&vda_ctx->queue_mutex, NULL);
00144
00145 config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
00146 4,
00147 &kCFTypeDictionaryKeyCallBacks,
00148 &kCFTypeDictionaryValueCallBacks);
00149
00150 height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->height);
00151 width = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->width);
00152 format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->format);
00153 avc_data = CFDataCreate(kCFAllocatorDefault, extradata, extradata_size);
00154
00155 CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height);
00156 CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width);
00157 CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format);
00158 CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data);
00159
00160 buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
00161 2,
00162 &kCFTypeDictionaryKeyCallBacks,
00163 &kCFTypeDictionaryValueCallBacks);
00164 io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
00165 0,
00166 &kCFTypeDictionaryKeyCallBacks,
00167 &kCFTypeDictionaryValueCallBacks);
00168 cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault,
00169 kCFNumberSInt32Type,
00170 &vda_ctx->cv_pix_fmt_type);
00171 CFDictionarySetValue(buffer_attributes,
00172 kCVPixelBufferPixelFormatTypeKey,
00173 cv_pix_fmt);
00174 CFDictionarySetValue(buffer_attributes,
00175 kCVPixelBufferIOSurfacePropertiesKey,
00176 io_surface_properties);
00177
00178 status = VDADecoderCreate(config_info,
00179 buffer_attributes,
00180 vda_decoder_callback,
00181 vda_ctx,
00182 &vda_ctx->decoder);
00183
00184 CFRelease(height);
00185 CFRelease(width);
00186 CFRelease(format);
00187 CFRelease(avc_data);
00188 CFRelease(config_info);
00189 CFRelease(io_surface_properties);
00190 CFRelease(cv_pix_fmt);
00191 CFRelease(buffer_attributes);
00192
00193 if (kVDADecoderNoErr != status)
00194 return status;
00195
00196 return 0;
00197 }
00198
00199 int ff_vda_destroy_decoder(struct vda_context *vda_ctx)
00200 {
00201 OSStatus status = kVDADecoderNoErr;
00202
00203 if (vda_ctx->decoder)
00204 status = VDADecoderDestroy(vda_ctx->decoder);
00205
00206 vda_clear_queue(vda_ctx);
00207
00208 pthread_mutex_destroy(&vda_ctx->queue_mutex);
00209
00210 if (kVDADecoderNoErr != status)
00211 return status;
00212
00213 return 0;
00214 }
00215
00216 vda_frame *ff_vda_queue_pop(struct vda_context *vda_ctx)
00217 {
00218 vda_frame *top_frame;
00219
00220 if (!vda_ctx->queue)
00221 return NULL;
00222
00223 pthread_mutex_lock(&vda_ctx->queue_mutex);
00224 top_frame = vda_ctx->queue;
00225 vda_ctx->queue = top_frame->next_frame;
00226 pthread_mutex_unlock(&vda_ctx->queue_mutex);
00227
00228 return top_frame;
00229 }
00230
00231 void ff_vda_release_vda_frame(vda_frame *frame)
00232 {
00233 if (frame) {
00234 CVPixelBufferRelease(frame->cv_buffer);
00235 av_freep(&frame);
00236 }
00237 }
00238
00239 int ff_vda_decoder_decode(struct vda_context *vda_ctx,
00240 uint8_t *bitstream,
00241 int bitstream_size,
00242 int64_t frame_pts)
00243 {
00244 OSStatus status = kVDADecoderNoErr;
00245 CFDictionaryRef user_info;
00246 CFDataRef coded_frame;
00247
00248 coded_frame = CFDataCreate(kCFAllocatorDefault, bitstream, bitstream_size);
00249 user_info = vda_dictionary_with_pts(frame_pts);
00250 status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, user_info);
00251
00252 CFRelease(user_info);
00253 CFRelease(coded_frame);
00254
00255 if (kVDADecoderNoErr != status)
00256 return status;
00257
00258 return 0;
00259 }