コード例 #1
0
        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;
            }
        }
コード例 #2
0
 internal DataOwner(T value, DataTransfer <T> parent)
 {
     Value   = value;
     _parent = parent;
 }