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(); }; }
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(); }