static VTDecompressionSessionRef gst_vtdec_create_session (GstVTDec * self, CMFormatDescriptionRef fmt_desc) { VTDecompressionSessionRef session = NULL; GstCVApi *cv = self->ctx->cv; CFMutableDictionaryRef pb_attrs; VTDecompressionOutputCallback callback; VTStatus status; pb_attrs = CFDictionaryCreateMutable (NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferPixelFormatTypeKey), kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange); gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferWidthKey), self->vinfo.width); gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferHeightKey), self->vinfo.height); gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferBytesPerRowAlignmentKey), 2 * self->vinfo.width); callback.func = gst_vtdec_enqueue_frame; callback.data = self; status = self->ctx->vt->VTDecompressionSessionCreate (NULL, fmt_desc, NULL, pb_attrs, &callback, &session); GST_INFO_OBJECT (self, "VTDecompressionSessionCreate for %d x %d => %d", self->vinfo.width, self->vinfo.height, status); CFRelease (pb_attrs); return session; }
static CMFormatDescriptionRef gst_vtdec_create_format_description_from_codec_data (GstVTDec * self, GstBuffer * codec_data) { CMFormatDescriptionRef fmt_desc; CFMutableDictionaryRef extensions, par, atoms; GstMapInfo map; OSStatus status; gst_buffer_map (codec_data, &map, GST_MAP_READ); /* CVPixelAspectRatio dict */ par = CFDictionaryCreateMutable (NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); gst_vtutil_dict_set_i32 (par, CFSTR ("HorizontalSpacing"), self->vinfo.par_n); gst_vtutil_dict_set_i32 (par, CFSTR ("VerticalSpacing"), self->vinfo.par_d); /* SampleDescriptionExtensionAtoms dict */ atoms = CFDictionaryCreateMutable (NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); gst_vtutil_dict_set_data (atoms, CFSTR ("avcC"), map.data, map.size); /* Extensions dict */ extensions = CFDictionaryCreateMutable (NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); gst_vtutil_dict_set_string (extensions, CFSTR ("CVImageBufferChromaLocationBottomField"), "left"); gst_vtutil_dict_set_string (extensions, CFSTR ("CVImageBufferChromaLocationTopField"), "left"); gst_vtutil_dict_set_boolean (extensions, CFSTR("FullRangeVideo"), FALSE); gst_vtutil_dict_set_object (extensions, CFSTR ("CVPixelAspectRatio"), (CFTypeRef *) par); gst_vtutil_dict_set_object (extensions, CFSTR ("SampleDescriptionExtensionAtoms"), (CFTypeRef *) atoms); status = CMVideoFormatDescriptionCreate (NULL, self->details->format_id, self->vinfo.width, self->vinfo.height, extensions, &fmt_desc); gst_buffer_unmap (codec_data, &map); if (status == noErr) return fmt_desc; else return NULL; }
static OSStatus gst_vtdec_create_session (GstVtdec * vtdec, GstVideoFormat format, gboolean enable_hardware) { CFMutableDictionaryRef output_image_buffer_attrs; VTDecompressionOutputCallbackRecord callback; CFMutableDictionaryRef videoDecoderSpecification; OSStatus status; guint32 cv_format = 0; g_return_val_if_fail (vtdec->session == NULL, FALSE); switch (format) { case GST_VIDEO_FORMAT_NV12: cv_format = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; break; case GST_VIDEO_FORMAT_UYVY: cv_format = kCVPixelFormatType_422YpCbCr8; break; case GST_VIDEO_FORMAT_RGBA: cv_format = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; break; default: g_warn_if_reached (); break; } videoDecoderSpecification = CFDictionaryCreateMutable (NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); /* This is the default on iOS and the key does not exist there */ #ifndef HAVE_IOS gst_vtutil_dict_set_boolean (videoDecoderSpecification, kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder, enable_hardware); if (enable_hardware && vtdec->require_hardware) gst_vtutil_dict_set_boolean (videoDecoderSpecification, kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder, TRUE); #endif output_image_buffer_attrs = CFDictionaryCreateMutable (NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); gst_vtutil_dict_set_i32 (output_image_buffer_attrs, kCVPixelBufferPixelFormatTypeKey, cv_format); gst_vtutil_dict_set_i32 (output_image_buffer_attrs, kCVPixelBufferWidthKey, vtdec->video_info.width); gst_vtutil_dict_set_i32 (output_image_buffer_attrs, kCVPixelBufferHeightKey, vtdec->video_info.height); callback.decompressionOutputCallback = gst_vtdec_session_output_callback; callback.decompressionOutputRefCon = vtdec; status = VTDecompressionSessionCreate (NULL, vtdec->format_description, videoDecoderSpecification, output_image_buffer_attrs, &callback, &vtdec->session); CFRelease (output_image_buffer_attrs); return status; }
static VTCompressionSessionRef gst_vtenc_create_session (GstVTEnc * self) { VTCompressionSessionRef session = NULL; GstCVApi *cv = self->ctx->cv; GstVTApi *vt = self->ctx->vt; CFMutableDictionaryRef pb_attrs; VTCompressionOutputCallback callback; VTStatus status; pb_attrs = CFDictionaryCreateMutable (NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferPixelFormatTypeKey), kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange); gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferWidthKey), self->negotiated_width); gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferHeightKey), self->negotiated_height); callback.func = gst_vtenc_enqueue_buffer; callback.data = self; status = vt->VTCompressionSessionCreate (NULL, self->negotiated_width, self->negotiated_height, self->details->format_id, 0, pb_attrs, 0, callback, &session); GST_INFO_OBJECT (self, "VTCompressionSessionCreate for %d x %d => %d", self->negotiated_width, self->negotiated_height, status); if (status != kVTSuccess) goto beach; if (self->dump_properties) { gst_vtenc_session_dump_properties (self, session); self->dump_properties = FALSE; } gst_vtenc_session_configure_usage (self, session, gst_vtenc_get_usage (self)); gst_vtenc_session_configure_expected_framerate (self, session, (gdouble) self->negotiated_fps_n / (gdouble) self->negotiated_fps_d); gst_vtenc_session_configure_expected_duration (self, session, (gdouble) self->negotiated_fps_d / (gdouble) self->negotiated_fps_n); status = vt->VTCompressionSessionSetProperty (session, *(vt->kVTCompressionPropertyKey_ProfileLevel), *(vt->kVTProfileLevel_H264_Baseline_3_0)); GST_DEBUG_OBJECT (self, "kVTCompressionPropertyKey_ProfileLevel => %d", status); status = vt->VTCompressionSessionSetProperty (session, *(vt->kVTCompressionPropertyKey_AllowTemporalCompression), kCFBooleanTrue); GST_DEBUG_OBJECT (self, "kVTCompressionPropertyKey_AllowTemporalCompression => %d", status); gst_vtenc_session_configure_max_keyframe_interval (self, session, 0); gst_vtenc_session_configure_max_keyframe_interval_duration (self, session, G_MAXDOUBLE); gst_vtenc_session_configure_bitrate (self, session, gst_vtenc_get_bitrate (self)); beach: CFRelease (pb_attrs); return session; }