public Decoder(string format, string camera, DataTransfer <MatAndBuffer> dataTransfer, bool enableHardware = false) { _dataTransfer = dataTransfer; var inputFormat = ffmpeg.av_find_input_format(format); if (inputFormat == null) { throw new ApplicationException($"Failed to find input format '{format}'"); } var inputContext = ffmpeg.avformat_alloc_context(); try { AVDictionary *options = null; ffmpeg.av_dict_set(&options, "video_size", "640x480", ffmpeg.AV_DICT_APPEND); ffmpeg.avformat_open_input(&inputContext, camera, inputFormat, &options).ThrowExceptionIfError(); ffmpeg.av_dict_free(&options); options = null; try { ffmpeg.avformat_find_stream_info(inputContext, null).ThrowExceptionIfError(); AVCodec *decoder; var videoStream = ffmpeg.av_find_best_stream(inputContext, AVMediaType.AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0); if (videoStream < 0) { throw new ApplicationException("No video stream found"); } AVBufferRef *hwDeviceContext = null; var(hwPixelFormat, pixelFormat) = enableHardware ? SortoutHardware(decoder, out hwDeviceContext) : (AVPixelFormat.AV_PIX_FMT_NONE, AVPixelFormat.AV_PIX_FMT_NONE); var decoderContext = ffmpeg.avcodec_alloc_context3(decoder); var video = inputContext->streams[videoStream]; video->discard = AVDiscard.AVDISCARD_NONKEY; ffmpeg.avcodec_parameters_to_context(decoderContext, video->codecpar).ThrowExceptionIfError(); if (hwPixelFormat != AVPixelFormat.AV_PIX_FMT_NONE) { AVCodecContext_get_format getFormat = (_, formats) => { //AVPixelFormat* pixelFormat; for (var pixelFormat = formats; *pixelFormat != AVPixelFormat.AV_PIX_FMT_NONE; pixelFormat++) { if (*pixelFormat == hwPixelFormat) { return(*pixelFormat); } } throw new ApplicationException("Failed to get hardware pixel format"); }; decoderContext->get_format = getFormat; } ffmpeg.av_opt_set_int(decoderContext, "refcounted_frames", 1, 0); if (hwPixelFormat != AVPixelFormat.AV_PIX_FMT_NONE) { decoderContext->hw_device_ctx = ffmpeg.av_buffer_ref(hwDeviceContext); } else { pixelFormat = ConvertFormat(video->codec->pix_fmt); } ffmpeg.avcodec_open2(decoderContext, decoder, null).ThrowExceptionIfError(); // Now all opened _inputContext = inputContext; _decoderContext = decoderContext; CodecName = ffmpeg.avcodec_get_name(decoder->id); FrameSize = new System.Drawing.Size(video->codec->width, video->codec->height); PixelFormat = pixelFormat; StreamIndex = videoStream; _hwPixelFormat = hwPixelFormat; _converter = new Converter(FrameSize, pixelFormat); Console.WriteLine($"Opened stream {StreamIndex} of {CodecName} as {FrameSize.Width} x {FrameSize.Height} @ {PixelFormat}"); } catch (Exception) { ffmpeg.avformat_close_input(&inputContext); throw; } } catch (Exception) { ffmpeg.avformat_free_context(inputContext); throw; } }
internal DataOwner(T value, DataTransfer <T> parent) { Value = value; _parent = parent; }