public unsafe void CreateVideoDecoder(String path, AVInputFormat *avInputFormat, bool repeat = false, bool isCamera = false)
        {
            _videoDecoder = new FFmpegVideoDecoder(path, avInputFormat, repeat, isCamera);
            _videoDecoder.OnVideoFrame += VideoDecoder_OnVideoFrame;

            _videoDecoder.OnEndOfFile += () =>
            {
                logger.LogDebug($"File source decode complete for {path}.");
                OnEndOfFile?.Invoke();
                _videoDecoder.Dispose();
            };
        }
Exemple #2
0
        public unsafe void CreateAudioDecoder(String path, AVInputFormat *avInputFormat, bool repeat = false, bool isMicrophone = false)
        {
            _audioDecoder = new FFmpegAudioDecoder(path, avInputFormat, repeat, isMicrophone);

            _audioDecoder.OnAudioFrame += AudioDecoder_OnAudioFrame;

            _audioDecoder.OnEndOfFile += () =>
            {
                logger.LogDebug($"File source decode complete for {path}.");
                OnEndOfFile?.Invoke();
                _audioDecoder.Dispose();
            };
        }
        public FFmpegFileSource(string path, bool repeat, IAudioEncoder audioEncoder)
        {
            if (!File.Exists(path))
            {
                throw new ApplicationException($"Requested path for FFmpeg file source could not be found {path}.");
            }

            _audioFormatManager = new MediaFormatManager <AudioFormat>(_supportedAudioFormats);
            _videoFormatManager = new MediaFormatManager <VideoFormat>(_supportedVideoFormats);

            _audioEncoder      = audioEncoder;
            _fileSourceDecoder = new FileSourceDecoder(path, repeat);
            _videoEncoder      = new FFmpegVideoEncoder();
            _fileSourceDecoder.OnVideoFrame += FileSourceDecoder_OnVideoFrame;
            _fileSourceDecoder.OnAudioFrame += FileSourceDecoder_OnAudioFrame;
            _fileSourceDecoder.OnEndOfFile  += () =>
            {
                logger.LogDebug($"File source decode complete for {path}.");
                OnEndOfFile?.Invoke();
                _fileSourceDecoder.Dispose();
            };
        }
        private unsafe void RunDecodeLoop()
        {
            AVPacket *pkt     = ffmpeg.av_packet_alloc();
            AVFrame * avFrame = ffmpeg.av_frame_alloc();

            int eagain = ffmpeg.AVERROR(ffmpeg.EAGAIN);
            int error;

            bool canContinue  = true;
            bool managePacket = true;

            double firts_dpts = 0;

            double original_dpts = 0;

            try
            {
                // Decode loop.
                pkt = ffmpeg.av_packet_alloc();

Repeat:

                DateTime startTime = DateTime.Now;

                while (!_isClosed && !_isPaused && canContinue)
                {
                    error = ffmpeg.av_read_frame(_fmtCtx, pkt);
                    if (error < 0)
                    {
                        managePacket = false;
                        if (error == eagain)
                        {
                            ffmpeg.av_packet_unref(pkt);
                        }
                        else
                        {
                            canContinue = false;
                        }
                    }
                    else
                    {
                        managePacket = true;
                    }

                    if (managePacket)
                    {
                        if (pkt->stream_index == _audioStreamIndex)
                        {
                            ffmpeg.avcodec_send_packet(_audDecCtx, pkt).ThrowExceptionIfError();
                            int recvRes = ffmpeg.avcodec_receive_frame(_audDecCtx, avFrame);
                            while (recvRes >= 0)
                            {
                                OnAudioFrame?.Invoke(ref *avFrame);


                                if (!_isMicrophone)
                                {
                                    double dpts = 0;
                                    if (avFrame->pts != ffmpeg.AV_NOPTS_VALUE)
                                    {
                                        dpts          = _audioTimebase * avFrame->pts;
                                        original_dpts = dpts;

                                        if (firts_dpts == 0)
                                        {
                                            firts_dpts = dpts;
                                        }

                                        dpts -= firts_dpts;
                                    }
                                    int sleep = (int)(dpts * 1000 - DateTime.Now.Subtract(startTime).TotalMilliseconds);
                                    Console.WriteLine($"sleep {sleep} {Math.Min(_maxAudioFrameSpace, sleep)} - firts_dpts:{firts_dpts} - dpts:{dpts} - original_dpts:{original_dpts}");


                                    if (sleep > Helper.MIN_SLEEP_MILLISECONDS)
                                    {
                                        ffmpeg.av_usleep((uint)(Math.Min(_maxAudioFrameSpace, sleep) * 1000));
                                    }
                                }

                                recvRes = ffmpeg.avcodec_receive_frame(_audDecCtx, avFrame);
                            }

                            if (recvRes < 0 && recvRes != ffmpeg.AVERROR(ffmpeg.EAGAIN))
                            {
                                recvRes.ThrowExceptionIfError();
                            }
                        }

                        ffmpeg.av_packet_unref(pkt);
                    }
                }

                if (_isPaused)
                {
                    ((int)ffmpeg.avio_seek(_fmtCtx->pb, 0, ffmpeg.AVIO_SEEKABLE_NORMAL)).ThrowExceptionIfError();

                    ffmpeg.avformat_seek_file(_fmtCtx, _audioStreamIndex, 0, 0, _fmtCtx->streams[_audioStreamIndex]->duration, 0).ThrowExceptionIfError();
                }
                else
                {
                    logger.LogDebug($"FFmpeg end of file for source {_sourceUrl}.");

                    if (!_isClosed && _repeat)
                    {
                        ((int)ffmpeg.avio_seek(_fmtCtx->pb, 0, ffmpeg.AVIO_SEEKABLE_NORMAL)).ThrowExceptionIfError();

                        ffmpeg.avformat_seek_file(_fmtCtx, _audioStreamIndex, 0, 0, _fmtCtx->streams[_audioStreamIndex]->duration, 0).ThrowExceptionIfError();

                        canContinue = true;
                        goto Repeat;
                    }
                    else
                    {
                        OnEndOfFile?.Invoke();
                    }
                }
            }
            finally
            {
                ffmpeg.av_frame_unref(avFrame);
                ffmpeg.av_free(avFrame);

                ffmpeg.av_packet_unref(pkt);
                ffmpeg.av_free(pkt);
            }
        }
 private void _FFmpegAudioSource_OnEndOfFile()
 {
     OnEndOfFile?.Invoke();
 }