/// <summary> /// Creates a frame source object given the raw FFmpeg frame reference. /// </summary> /// <param name="framePointer">The raw FFmpeg frame pointer.</param> /// <returns>The media frame</returns> protected override unsafe MediaFrame CreateFrameSource(IntPtr framePointer) { // Validate the audio frame var frame = (AVFrame *)framePointer; if (frame == null || (*frame).extended_data == null || frame->channels <= 0 || frame->nb_samples <= 0 || frame->sample_rate <= 0) { return(null); } if (string.IsNullOrWhiteSpace(FilterString) == false) { InitializeFilterGraph(frame); } AVFrame *outputFrame = null; // Filtergraph can be changed by issuing a ChangeMedia command if (FilterGraph != null) { // Allocate the output frame outputFrame = MediaFrame.CloneAVFrame(frame); var result = ffmpeg.av_buffersrc_add_frame(SourceFilter, outputFrame); while (result >= 0) { result = ffmpeg.av_buffersink_get_frame_flags(SinkFilter, outputFrame, 0); } if (outputFrame->nb_samples <= 0) { // If we don't have a valid output frame simply release it and // return the original input frame MediaFrame.ReleaseAVFrame(outputFrame); outputFrame = frame; } else { // the output frame is the new valid frame (output frame). // threfore, we need to release the original MediaFrame.ReleaseAVFrame(frame); } } else { outputFrame = frame; } // Check if the output frame is valid if (outputFrame->nb_samples <= 0) { return(null); } var frameHolder = new AudioFrame(outputFrame, this); return(frameHolder); }
/// <inheritdoc /> protected override MediaFrame CreateFrameSource(IntPtr framePointer) { // Validate the video frame var frame = (AVFrame *)framePointer; if (framePointer == IntPtr.Zero || frame->width <= 0 || frame->height <= 0) { return(null); } // Move the frame from hardware (GPU) memory to RAM (CPU) if (HardwareAccelerator != null) { frame = HardwareAccelerator.ExchangeFrame(CodecContext, frame, out var isHardwareFrame); IsUsingHardwareDecoding = isHardwareFrame; } // Init the filter graph for the frame if (string.IsNullOrWhiteSpace(FilterString) == false) { InitializeFilterGraph(frame); } AVFrame *outputFrame; // Changes in the filter graph can be applied by calling the ChangeMedia command if (FilterGraph != null) { // Allocate the output frame outputFrame = MediaFrame.CloneAVFrame(frame); var result = ffmpeg.av_buffersrc_add_frame(SourceFilter, outputFrame); while (result >= 0) { result = ffmpeg.av_buffersink_get_frame_flags(SinkFilter, outputFrame, 0); } if (outputFrame->width <= 0 || outputFrame->height <= 0) { // If we don't have a valid output frame simply release it and // return the original input frame MediaFrame.ReleaseAVFrame(outputFrame); outputFrame = frame; } else { // the output frame is the new valid frame (output frame). // therefore, we need to release the original MediaFrame.ReleaseAVFrame(frame); } } else { outputFrame = frame; } // Check if the output frame is valid if (outputFrame->width <= 0 || outputFrame->height <= 0) { return(null); } // Create the frame holder object and return it. return(new VideoFrame(outputFrame, this)); }