static void libav_decode_video(struct media_codec *mc, struct video_decoder *vd, struct media_queue *mq, struct media_buf *mb, int reqsize) { int got_pic = 0; media_pipe_t *mp = vd->vd_mp; AVCodecContext *ctx = mc->ctx; AVFrame *frame = vd->vd_frame; int t; if(mb->mb_flush) libav_video_eof(mc, vd, mq); copy_mbm_from_mb(&vd->vd_reorder[vd->vd_reorder_ptr], mb); ctx->reordered_opaque = vd->vd_reorder_ptr; vd->vd_reorder_ptr = (vd->vd_reorder_ptr + 1) & VIDEO_DECODER_REORDER_MASK; /* * If we are seeking, drop any non-reference frames */ ctx->skip_frame = mb->mb_skip == 1 ? AVDISCARD_NONREF : AVDISCARD_DEFAULT; avgtime_start(&vd->vd_decode_time); avcodec_decode_video2(ctx, frame, &got_pic, &mb->mb_pkt); t = avgtime_stop(&vd->vd_decode_time, mq->mq_prop_decode_avg, mq->mq_prop_decode_peak); if(mp->mp_stats) mp_set_mq_meta(mq, ctx->codec, ctx); if(got_pic == 0) return; const media_buf_meta_t *mbm = &vd->vd_reorder[frame->reordered_opaque]; if(!mbm->mbm_skip) libav_deliver_frame(vd, mp, mq, ctx, frame, mbm, t, mc); av_frame_unref(frame); }
static void vtb_decode(struct media_codec *mc, struct video_decoder *vd, struct media_queue *mq, struct media_buf *mb, int reqsize) { vtb_decoder_t *vtbd = mc->opaque; VTDecodeInfoFlags infoflags; int flags = kVTDecodeFrame_EnableAsynchronousDecompression | kVTDecodeFrame_EnableTemporalProcessing; OSStatus status; CMBlockBufferRef block_buf; CMSampleBufferRef sample_buf; vtbd->vtbd_vd = vd; status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, mb->mb_data, mb->mb_size, kCFAllocatorNull, NULL, 0, mb->mb_size, 0, &block_buf); if(status) { TRACE(TRACE_ERROR, "VTB", "Data buffer allocation error %d", status); return; } CMSampleTimingInfo ti; ti.duration = CMTimeMake(mb->mb_duration, 1000000); ti.presentationTimeStamp = CMTimeMake(mb->mb_pts, 1000000); ti.decodeTimeStamp = CMTimeMake(mb->mb_dts, 1000000); status = CMSampleBufferCreate(kCFAllocatorDefault, block_buf, TRUE, 0, 0, vtbd->vtbd_fmt, 1, 1, &ti, 0, NULL, &sample_buf); CFRelease(block_buf); if(status) { TRACE(TRACE_ERROR, "VTB", "Sample buffer allocation error %d", status); return; } void *frame_opaque = &vd->vd_reorder[vd->vd_reorder_ptr]; copy_mbm_from_mb(frame_opaque, mb); vd->vd_reorder_ptr = (vd->vd_reorder_ptr + 1) & VIDEO_DECODER_REORDER_MASK; if(mb->mb_skip) flags |= kVTDecodeFrame_DoNotOutputFrame; status = VTDecompressionSessionDecodeFrame(vtbd->vtbd_session, sample_buf, flags, frame_opaque, &infoflags); CFRelease(sample_buf); if(status) { TRACE(TRACE_ERROR, "VTB", "Decoding error %d", status); } hts_mutex_lock(&vtbd->vtbd_mutex); if(vtbd->vtbd_flush_to != PTS_UNSET) { vtb_frame_t *vf; while((vf = LIST_FIRST(&vtbd->vtbd_frames)) != NULL) { if(vtbd->vtbd_flush_to < vf->vf_mbm.mbm_pts) break; LIST_REMOVE(vf, vf_link); hts_mutex_unlock(&vtbd->vtbd_mutex); emit_frame(vtbd, vf, mq); hts_mutex_lock(&vtbd->vtbd_mutex); CFRelease(vf->vf_buf); free(vf); } } hts_mutex_unlock(&vtbd->vtbd_mutex); }