static void gst_vtdec_enqueue_frame (void *data1, void *data2, VTStatus result, VTDecodeInfoFlags info, CVBufferRef cvbuf, CMTime pts, CMTime duration) { GstVTDec *self = GST_VTDEC_CAST (data1); GstBuffer *src_buf = GST_BUFFER (data2); GstBuffer *buf; if (result != kVTSuccess) { GST_ERROR_OBJECT (self, "Error decoding frame %d", result); goto beach; } if (kVTDecodeInfo_FrameDropped & info) { GST_WARNING_OBJECT (self, "Frame dropped"); goto beach; } buf = gst_core_video_buffer_new (cvbuf, &self->vinfo); gst_buffer_copy_into (buf, src_buf, GST_BUFFER_COPY_METADATA, 0, -1); GST_BUFFER_PTS (buf) = pts.value; GST_BUFFER_DURATION (buf) = duration.value; g_queue_push_head (self->cur_outbufs, buf); if (GST_BUFFER_PTS (src_buf) <= GST_BUFFER_DTS (src_buf)) { GST_LOG_OBJECT (self, "Flushing interal queue of buffers"); self->flush = TRUE; } else { GST_LOG_OBJECT (self, "Queuing buffer"); } beach: return; }
static void gst_vtdec_session_output_callback (void *decompression_output_ref_con, void *source_frame_ref_con, OSStatus status, VTDecodeInfoFlags info_flags, CVImageBufferRef image_buffer, CMTime pts, CMTime duration) { GstVtdec *vtdec = (GstVtdec *) decompression_output_ref_con; GstVideoCodecFrame *frame = (GstVideoCodecFrame *) source_frame_ref_con; GstBuffer *buf; GstVideoCodecState *state; GST_LOG_OBJECT (vtdec, "got output frame %p %d and VT buffer %p", frame, frame->decode_frame_number, image_buffer); if (status != noErr) { GST_ERROR_OBJECT (vtdec, "Error decoding frame %d", (int) status); goto drop; } if (image_buffer == NULL) { if (info_flags & kVTDecodeInfo_FrameDropped) GST_DEBUG_OBJECT (vtdec, "Frame dropped by video toolbox"); else GST_DEBUG_OBJECT (vtdec, "Decoded frame is NULL"); goto drop; } /* FIXME: use gst_video_decoder_allocate_output_buffer */ state = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (vtdec)); if (state == NULL) { GST_WARNING_OBJECT (vtdec, "Output state not configured, release buffer"); /* release as this usually means that the baseclass isn't ready to do * the QoS that _drop requires and will lead to an assertion with the * segment.format being undefined */ goto release; } buf = gst_core_video_buffer_new (image_buffer, &state->info, vtdec->texture_cache == NULL); gst_video_codec_state_unref (state); GST_BUFFER_PTS (buf) = pts.value; GST_BUFFER_DURATION (buf) = duration.value; frame->output_buffer = buf; g_async_queue_push_sorted (vtdec->reorder_queue, frame, sort_frames_by_pts, NULL); return; drop: GST_WARNING_OBJECT (vtdec, "Frame dropped %p %d", frame, frame->decode_frame_number); gst_video_decoder_drop_frame (GST_VIDEO_DECODER (vtdec), frame); return; release: GST_WARNING_OBJECT (vtdec, "Frame released %p %d", frame, frame->decode_frame_number); gst_video_decoder_release_frame (GST_VIDEO_DECODER (vtdec), frame); return; }
static void gst_vtdec_session_output_callback (void *decompression_output_ref_con, void *source_frame_ref_con, OSStatus status, VTDecodeInfoFlags info_flags, CVImageBufferRef image_buffer, CMTime pts, CMTime duration) { GstVtdec *vtdec = (GstVtdec *) decompression_output_ref_con; GstVideoCodecFrame *frame = (GstVideoCodecFrame *) source_frame_ref_con; GstVideoCodecState *state; GST_LOG_OBJECT (vtdec, "got output frame %p %d and VT buffer %p", frame, frame->decode_frame_number, image_buffer); frame->output_buffer = NULL; if (status != noErr) { GST_ERROR_OBJECT (vtdec, "Error decoding frame %d", (int) status); } if (image_buffer) { GstBuffer *buf = NULL; /* FIXME: use gst_video_decoder_allocate_output_buffer */ state = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (vtdec)); if (state == NULL) { GST_WARNING_OBJECT (vtdec, "Output state not configured, release buffer"); frame->flags &= VTDEC_FRAME_FLAG_SKIP; } else { buf = gst_core_video_buffer_new (image_buffer, &state->info, vtdec->texture_cache); gst_video_codec_state_unref (state); GST_BUFFER_PTS (buf) = pts.value; GST_BUFFER_DURATION (buf) = duration.value; frame->output_buffer = buf; } } else { if (info_flags & kVTDecodeInfo_FrameDropped) { GST_DEBUG_OBJECT (vtdec, "Frame dropped by video toolbox %p %d", frame, frame->decode_frame_number); frame->flags |= VTDEC_FRAME_FLAG_DROP; } else { GST_DEBUG_OBJECT (vtdec, "Decoded frame is NULL"); frame->flags |= VTDEC_FRAME_FLAG_SKIP; } } g_async_queue_push_sorted (vtdec->reorder_queue, frame, sort_frames_by_pts, NULL); }
static void gst_vtdec_enqueue_frame (void *data, gsize unk1, VTStatus result, gsize unk2, CVBufferRef cvbuf) { GstVTDec *self = GST_VTDEC_CAST (data); GstBuffer *buf; if (result != kVTSuccess) goto beach; buf = gst_core_video_buffer_new (self->ctx, cvbuf, &self->vinfo); gst_buffer_copy_into (buf, self->cur_inbuf, GST_BUFFER_COPY_METADATA, 0, -1); g_ptr_array_add (self->cur_outbufs, buf); beach: return; }