static GstFlowReturn gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf) { GstVTApi *vt = self->ctx->vt; CMSampleBufferRef sbuf; VTStatus status; VTDecodeFrameFlags frame_flags = 0; GstFlowReturn ret = GST_FLOW_OK; sbuf = gst_vtdec_sample_buffer_from (self, buf); self->flush = FALSE; status = vt->VTDecompressionSessionDecodeFrame (self->session, sbuf, frame_flags, buf, NULL); if (status != 0) { GST_WARNING_OBJECT (self, "VTDecompressionSessionDecodeFrame returned %d", status); } status = vt->VTDecompressionSessionWaitForAsynchronousFrames (self->session); if (status != 0) { GST_WARNING_OBJECT (self, "VTDecompressionSessionWaitForAsynchronousFrames returned %d", status); } CFRelease (sbuf); gst_buffer_unref (buf); if (self->flush) { if (!gst_vtdec_negotiate_downstream (self)) { ret = GST_FLOW_NOT_NEGOTIATED; goto error; } g_queue_sort (self->cur_outbufs, (GCompareDataFunc) _sort_buffers, NULL); while (!g_queue_is_empty (self->cur_outbufs)) { buf = g_queue_pop_head (self->cur_outbufs); GST_LOG_OBJECT (self, "Pushing buffer with PTS:%" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (buf))); ret = gst_pad_push (self->srcpad, buf); if (ret != GST_FLOW_OK) { goto error; } } }; exit: return ret; error: { g_queue_free_full (self->cur_outbufs, (GDestroyNotify) gst_buffer_unref); self->cur_outbufs = g_queue_new (); goto exit; } }
static GstFlowReturn gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf) { GstVTApi *vt = self->ctx->vt; CMSampleBufferRef sbuf; VTStatus status; GstFlowReturn ret = GST_FLOW_OK; guint i; self->cur_inbuf = buf; sbuf = gst_vtdec_sample_buffer_from (self, buf); status = vt->VTDecompressionSessionDecodeFrame (self->session, sbuf, 0, 0, 0); if (status != 0) { GST_WARNING_OBJECT (self, "VTDecompressionSessionDecodeFrame returned %d", status); } status = vt->VTDecompressionSessionWaitForAsynchronousFrames (self->session); if (status != 0) { GST_WARNING_OBJECT (self, "VTDecompressionSessionWaitForAsynchronousFrames returned %d", status); } self->ctx->cm->FigSampleBufferRelease (sbuf); self->cur_inbuf = NULL; gst_buffer_unref (buf); if (self->cur_outbufs->len > 0) { if (!gst_vtdec_negotiate_downstream (self)) ret = GST_FLOW_NOT_NEGOTIATED; } for (i = 0; i != self->cur_outbufs->len; i++) { GstBuffer *buf = g_ptr_array_index (self->cur_outbufs, i); if (ret == GST_FLOW_OK) { ret = gst_pad_push (self->srcpad, buf); } else { gst_buffer_unref (buf); } } g_ptr_array_set_size (self->cur_outbufs, 0); return ret; }
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; }