/// <summary> /// Extracts the programs from the input and creates associations between programs and streams. /// </summary> /// <param name="ic">The ic.</param> /// <param name="streams">The streams.</param> /// <returns>The program information</returns> private static List <ProgramInfo> ExtractPrograms(AVFormatContext *ic, ReadOnlyDictionary <int, StreamInfo> streams) { var result = new List <ProgramInfo>(); if (ic->programs == null) { return(result); } for (var i = 0; i < ic->nb_programs; i++) { var p = ic->programs[i]; var program = new ProgramInfo { Metadata = new ReadOnlyDictionary <string, string>(FFDictionary.ToDictionary(p->metadata)), ProgramId = p->id, ProgramNumber = p->program_num, }; var associatedStreams = new List <StreamInfo>(); for (var s = 0; s < p->nb_stream_indexes; s++) { var streamIndex = (int)p->stream_index[s]; if (streams.ContainsKey(streamIndex)) { associatedStreams.Add(streams[streamIndex]); } } program.Streams = new ReadOnlyCollection <StreamInfo>(associatedStreams); result.Add(program); } return(result); }
public MediaStream(Stream baseStream, bool write = false, AVOutputFormat *outputFormat = null) { if (write && !baseStream.CanWrite) { throw new ArgumentException($"流不能被写入,请确保Stream.CanWrite为true"); } if (baseStream.CanRead) { procRead = Read; } if (write && baseStream.CanWrite) { procWrite = Write; } if (baseStream.CanSeek) { procSeek = Seek; } this.baseStream = baseStream; try { formatContext = FF.avformat_alloc_context(); buffer = (byte *)FF.av_malloc((IntPtr)bufferLength); ioContext = FF.avio_alloc_context(buffer, bufferLength, write, null, procRead, procWrite, procSeek); if (write) { formatContext->Oformat = outputFormat; formatContext->Flags = AVFmtFlag.CustomIO; } formatContext->Pb = ioContext; } catch { Dispose(); throw; } }
private void Initialize() { AVCodecContext *codecCtxPtr; try { if (vStream != null) { codecCtxPtr = vCodecCtx; avcodec_free_context(&codecCtxPtr); } } catch (Exception e) { Log("Error[" + (-1).ToString("D4") + "], Msg: " + e.Message + "\n" + e.StackTrace); } try { if (fmtCtx != null) { AVFormatContext *fmtCtxPtr = fmtCtx; avformat_close_input(&fmtCtxPtr); } fmtCtx = null; vStream = null; } catch (Exception e) { Log("Error[" + (-1).ToString("D4") + "], Msg: " + e.Message + "\n" + e.StackTrace); } }
public VideoStreamDecoder(string fileName, AVHWDeviceType HWDeviceType = AVHWDeviceType.AV_HWDEVICE_TYPE_NONE) { _pFormatContext = ffmpeg.avformat_alloc_context(); if (_pFormatContext == null) { throw new Exception("Could not allocate the format context"); } _receivedFrame = ffmpeg.av_frame_alloc(); var pFormatContext = _pFormatContext; ffmpeg.avformat_open_input(&pFormatContext, fileName, null, null); ffmpeg.avformat_find_stream_info(_pFormatContext, null); AVCodec *codec = null; _streamIndex = ffmpeg.av_find_best_stream(_pFormatContext, AVMediaType.AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0); _pCodecContext = ffmpeg.avcodec_alloc_context3(codec); if (HWDeviceType != AVHWDeviceType.AV_HWDEVICE_TYPE_NONE) { ffmpeg.av_hwdevice_ctx_create(&_pCodecContext->hw_device_ctx, HWDeviceType, null, null, 0); } ffmpeg.avcodec_parameters_to_context(_pCodecContext, _pFormatContext->streams[_streamIndex]->codecpar); ffmpeg.avcodec_open2(_pCodecContext, codec, null); CodecName = ffmpeg.avcodec_get_name(codec->id); FrameSize = new Size(_pCodecContext->width, _pCodecContext->height); PixelFormat = _pCodecContext->pix_fmt; _pPacket = ffmpeg.av_packet_alloc(); _pFrame = ffmpeg.av_frame_alloc(); }
public void Test1() { MediaDictionary2 options = MediaDictionary2.Empty; Output.WriteLine($"{((IntPtr)options._handle).ToInt64()}"); Output.WriteLine($"={((IntPtr)(AVDictionary**)options).ToInt64()}"); options.Add("protocol_whitelist", "file"); options.Add("key", "value"); options.Add("protocol_blacklist", "cache"); Output.WriteLine($"{((IntPtr)options._handle).ToInt64()}"); Output.WriteLine($"={((IntPtr)(AVDictionary**)options).ToInt64()}"); var file = "111.mp4"; AVFormatContext * pFormatContext = null; AVFormatContext **ppFormatContext = &pFormatContext; var ret1 = ffmpeg.avformat_alloc_output_context2(ppFormatContext, OutFormat.Get("mpeg"), null, file); var ret2 = ffmpeg.avio_open2(&pFormatContext->pb, file, ffmpeg.AVIO_FLAG_WRITE, null, options); Output.WriteLine($"{((IntPtr)options._handle).ToInt64()}"); Output.WriteLine($"={((IntPtr)(AVDictionary**)options).ToInt64()}"); Output.WriteLine($"+{((IntPtr)(*(AVDictionary**)options)).ToInt64()}"); Assert.True(options.Count == 1); Assert.Equal("key", options.First().Key); Assert.Equal("value", options.First().Value); }
/// <inheritdoc /> public unsafe void OnAudioFrameDecoded(AVFrame *audioFrame, AVFormatContext *context) => Parent?.RaiseAudioFrameDecodedEvent(audioFrame, context);
/// <inheritdoc /> public unsafe void OnPacketRead(AVPacket *packet, AVFormatContext *context) => Parent?.RaisePacketReadEvent(packet, context);
static int OpenOutputFile(string filename) { AVStream * out_stream; AVStream * in_stream; AVCodecContext *dec_ctx; AVCodecContext *enc_ctx; AVCodec * encoder; int ret; ofmt_ctx = null; fixed(AVFormatContext **ctx = &ofmt_ctx) { ffmpeg.avformat_alloc_output_context2(ctx, null, null, filename); } if (null == ofmt_ctx) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Could not create output context\n"); return(ffmpeg.AVERROR_UNKNOWN); } for (int i = 0; i < ifmt_ctx->nb_streams; i++) { out_stream = ffmpeg.avformat_new_stream(ofmt_ctx, null); if (out_stream == null) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Failed allocating output stream\n"); return(ffmpeg.AVERROR_UNKNOWN); } in_stream = ifmt_ctx->streams[i]; dec_ctx = in_stream->codec; enc_ctx = out_stream->codec; if (dec_ctx->codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO) { encoder = ffmpeg.avcodec_find_encoder(AVCodecID.AV_CODEC_ID_H264); if (null == encoder) { ffmpeg.av_log(null, ffmpeg.AV_LOG_FATAL, "Neccessary encoder not found\n"); return(ffmpeg.AVERROR_INVALIDDATA); } enc_ctx->height = dec_ctx->height; enc_ctx->width = dec_ctx->width; enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio; enc_ctx->pix_fmt = encoder->pix_fmts[0]; enc_ctx->time_base = dec_ctx->time_base; // enc_ctx->me_range = 25; // enc_ctx->max_qdiff = 4; enc_ctx->qmin = 10; enc_ctx->qmax = 51; // enc_ctx->qcompress = 0.6; // enc_ctx->refs = 3; enc_ctx->max_b_frames = 3; enc_ctx->gop_size = 250; enc_ctx->bit_rate = 500000; enc_ctx->time_base.num = dec_ctx->time_base.num; enc_ctx->time_base.den = dec_ctx->time_base.den; ret = ffmpeg.avcodec_open2(enc_ctx, encoder, null); if (ret < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n"); return(ret); } //ffmpeg.av_opt_set(ofmt_ctx->priv_data, "preset", "superfast", 0); //ffmpeg.av_opt_set(ofmt_ctx->priv_data, "tune", "zerolatency", 0); ffmpeg.av_opt_set_int(ofmt_ctx->priv_data, "hls_time", 5, ffmpeg.AV_OPT_SEARCH_CHILDREN); ffmpeg.av_opt_set_int(ofmt_ctx->priv_data, "hls_list_size", 10, ffmpeg.AV_OPT_SEARCH_CHILDREN); } else if (dec_ctx->codec_type == AVMediaType.AVMEDIA_TYPE_UNKNOWN) { ffmpeg.av_log(null, ffmpeg.AV_LOG_FATAL, "Elementary stream #%d is of unknown type, cannot proceed\n"); return(ffmpeg.AVERROR_INVALIDDATA); } else if (dec_ctx->codec_type == AVMediaType.AVMEDIA_TYPE_AUDIO) { encoder = ffmpeg.avcodec_find_encoder(AVCodecID.AV_CODEC_ID_AAC); enc_ctx->sample_rate = dec_ctx->sample_rate; enc_ctx->channel_layout = dec_ctx->channel_layout; enc_ctx->channels = ffmpeg.av_get_channel_layout_nb_channels(enc_ctx->channel_layout); enc_ctx->sample_fmt = encoder->sample_fmts[0]; AVRational ar = new AVRational(); ar.num = 1; ar.den = enc_ctx->sample_rate; //{ 1, enc_ctx->sample_rate }; enc_ctx->time_base = ar; ret = ffmpeg.avcodec_open2(enc_ctx, encoder, null); if (ret < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n"); return(ret); } } else { ret = ffmpeg.avcodec_parameters_to_context(ofmt_ctx->streams[i]->codec, ofmt_ctx->streams[i]->codecpar); //ret = ffmpeg.avcodec_copy_context(ofmt_ctx->streams[i]->codec, ifmt_ctx->streams[i]->codec); if (ret < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Copying stream context failed\n"); return(ret); } ret = ffmpeg.avcodec_parameters_from_context(ifmt_ctx->streams[i]->codecpar, ifmt_ctx->streams[i]->codec); if (ret < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Copying stream context failed\n"); return(ret); } } if ((ofmt_ctx->oformat->flags & ffmpeg.AVFMT_GLOBALHEADER) > 0) { enc_ctx->flags |= ffmpeg.AV_CODEC_FLAG_GLOBAL_HEADER; } } ffmpeg.av_dump_format(ofmt_ctx, 0, filename, 1); // if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) { ret = ffmpeg.avio_open(&ofmt_ctx->pb, filename, ffmpeg.AVIO_FLAG_WRITE); if (ret < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Could not open output file '%s'"); return(ret); } // } /* init muxer, write output file header */ ret = ffmpeg.avformat_write_header(ofmt_ctx, null); if (ret < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Error occurred when opening output file\n"); return(ret); } return(0); }
private void DoStart() { var vss = Source; if (!_modeAudio) { vss = Tokenise(vss); } AVDictionary *options = null; if (_inputFormat == null) { ffmpeg.av_dict_set(&options, "analyzeduration", _analyzeDuration.ToString(), 0); string prefix = vss.ToLower().Substring(0, vss.IndexOf(":", StringComparison.Ordinal)); switch (prefix) { case "http": case "mmsh": case "mms": ffmpeg.av_dict_set(&options, "timeout", _timeout.ToString(), 0); ffmpeg.av_dict_set(&options, "stimeout", (_timeout * 1000).ToString(), 0); if (_cookies != "") { ffmpeg.av_dict_set(&options, "cookies", _cookies, 0); } if (_headers != "") { ffmpeg.av_dict_set(&options, "headers", _headers, 0); } if (_userAgent != "") { ffmpeg.av_dict_set(&options, "user-agent", _userAgent, 0); } break; case "tcp": case "udp": case "rtp": case "sdp": case "mmst": case "ftp": ffmpeg.av_dict_set(&options, "timeout", _timeout.ToString(), 0); break; case "rtsp": case "rtmp": ffmpeg.av_dict_set(&options, "stimeout", (_timeout * 1000).ToString(), 0); if (_userAgent != "") { ffmpeg.av_dict_set(&options, "user-agent", _userAgent, 0); } break; } ffmpeg.av_dict_set(&options, "rtsp_transport", RTSPmode, 0); } ffmpeg.av_dict_set(&options, "rtbufsize", "10000000", 0); var lo = _options.Split(Environment.NewLine.ToCharArray()); foreach (var nv in lo) { if (!string.IsNullOrEmpty(nv)) { var i = nv.IndexOf('='); if (i > -1) { var n = nv.Substring(0, i).Trim(); var v = nv.Substring(i + 1).Trim(); if (!string.IsNullOrEmpty(n) && !string.IsNullOrEmpty(v)) { int j; if (int.TryParse(v, out j)) { ffmpeg.av_dict_set_int(&options, n, j, 0); } else { ffmpeg.av_dict_set(&options, n, v, 0); } } } } } _stopReadingFrames = false; try { Program.FfmpegMutex.WaitOne(); var pFormatContext = ffmpeg.avformat_alloc_context(); _lastPacket = DateTime.UtcNow; _interruptCallback = InterruptCb; _interruptCallbackAddress = Marshal.GetFunctionPointerForDelegate(_interruptCallback); pFormatContext->interrupt_callback.callback = _interruptCallbackAddress; pFormatContext->interrupt_callback.opaque = null; if (ffmpeg.avformat_open_input(&pFormatContext, vss, _inputFormat, &options) != 0) { throw new ApplicationException(@"Could not open source"); } _formatContext = pFormatContext; SetupFormat(); } catch (Exception ex) { ErrorHandler?.Invoke(ex.Message); _res = ReasonToFinishPlaying.VideoSourceError; PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); } finally { try { Program.FfmpegMutex.ReleaseMutex(); } catch { } } _starting = false; }
/// <summary> /// Extracts the stream infos from the input. /// </summary> /// <param name="inputContext">The input context.</param> /// <returns>The list of stream infos.</returns> private static List <StreamInfo> ExtractStreams(AVFormatContext *inputContext) { var result = new List <StreamInfo>(32); if (inputContext->streams == null) { return(result); } for (var i = 0; i < inputContext->nb_streams; i++) { var s = inputContext->streams[i]; var codecContext = ffmpeg.avcodec_alloc_context3(null); ffmpeg.avcodec_parameters_to_context(codecContext, s->codecpar); // Fields which are missing from AVCodecParameters need to be taken // from the stream's AVCodecContext codecContext->properties = s->codec->properties; codecContext->codec = s->codec->codec; codecContext->qmin = s->codec->qmin; codecContext->qmax = s->codec->qmax; codecContext->coded_width = s->codec->coded_height; codecContext->coded_height = s->codec->coded_width; var bitsPerSample = codecContext->codec_type == AVMediaType.AVMEDIA_TYPE_AUDIO ? ffmpeg.av_get_bits_per_sample(codecContext->codec_id) : 0; var dar = s->display_aspect_ratio; var sar = s->sample_aspect_ratio; var codecSar = s->codecpar->sample_aspect_ratio; if (sar.num != 0 && (sar.num != codecSar.num || sar.den != codecSar.den)) { ffmpeg.av_reduce( &dar.num, &dar.den, s->codecpar->width * sar.num, s->codecpar->height * sar.den, 1024 * 1024); } var stream = new StreamInfo { StreamId = s->id, StreamIndex = s->index, Metadata = FFDictionary.ToDictionary(s->metadata), CodecType = codecContext->codec_type, CodecTypeName = ffmpeg.av_get_media_type_string(codecContext->codec_type), Codec = codecContext->codec_id, CodecName = ffmpeg.avcodec_get_name(codecContext->codec_id), CodecProfile = ffmpeg.avcodec_profile_name(codecContext->codec_id, codecContext->profile), ReferenceFrameCount = codecContext->refs, CodecTag = codecContext->codec_tag, PixelFormat = codecContext->pix_fmt, FieldOrder = codecContext->field_order, IsInterlaced = codecContext->field_order != AVFieldOrder.AV_FIELD_PROGRESSIVE && codecContext->field_order != AVFieldOrder.AV_FIELD_UNKNOWN, ColorRange = codecContext->color_range, PixelWidth = codecContext->width, PixelHeight = codecContext->height, HasClosedCaptions = (codecContext->properties & ffmpeg.FF_CODEC_PROPERTY_CLOSED_CAPTIONS) != 0, IsLossless = (codecContext->properties & ffmpeg.FF_CODEC_PROPERTY_LOSSLESS) != 0, BitRate = bitsPerSample > 0 ? bitsPerSample * codecContext->channels * codecContext->sample_rate : codecContext->bit_rate, MaxBitRate = codecContext->rc_max_rate, InfoFrameCount = s->codec_info_nb_frames, TimeBase = s->time_base, SampleFormat = codecContext->sample_fmt, SampleRate = codecContext->sample_rate, DisplayAspectRatio = dar, SampleAspectRatio = sar, Disposition = s->disposition, StartTime = s->start_time.ToTimeSpan(s->time_base), Duration = s->duration.ToTimeSpan(s->time_base), FPS = s->avg_frame_rate.ToDouble(), TBR = s->r_frame_rate.ToDouble(), TBN = 1d / s->time_base.ToDouble(), TBC = 1d / s->codec->time_base.ToDouble() }; // Extract valid hardware configurations stream.HardwareDevices = HardwareAccelerator.GetCompatibleDevices(stream.Codec); stream.HardwareDecoders = GetHardwareDecoders(stream.Codec); // TODO: I chose not to include Side data but I could easily do so // https://ffmpeg.org/doxygen/3.2/dump_8c_source.html // See function: dump_sidedata ffmpeg.avcodec_free_context(&codecContext); result.Add(stream); } return(result); }
/// <summary> /// Opens this media. /// </summary> /// <remarks> /// Once the media is open, the collection of <see cref="Streams"/> is populated. /// </remarks> public void Open(string url, long startPosition = 0, long length = -1) { FFmpegUtils.EnsurePlatformSupport(); if (isDisposed) { throw new ObjectDisposedException(nameof(FFmpegMedia)); } if (IsOpen) { // TODO: log? throw new InvalidOperationException(@"Media is already open."); } if (startPosition != 0 && length != -1) { url = $@"subfile,,start,{startPosition},end,{startPosition + length},,:{url}"; } var pFormatContext = ffmpeg.avformat_alloc_context(); var ret = ffmpeg.avformat_open_input(&pFormatContext, url, null, null); if (ret < 0) { Logger.Error($"Could not open file. Error code={ret.ToString("X8")}"); Logger.Error(GetErrorMessage(ret)); throw new ApplicationException(@"Could not open file."); } ret = ffmpeg.avformat_find_stream_info(pFormatContext, null); if (ret < 0) { Logger.Error($"Could not find stream info. Error code={ret.ToString("X8")}"); Logger.Error(GetErrorMessage(ret)); throw new ApplicationException(@"Could not find stream info."); } AVFormatContext = pFormatContext; Duration = TimeSpan.FromSeconds((double)AVFormatContext->duration / ffmpeg.AV_TIME_BASE); Url = url; // Get the streams for (int i = 0; i < pFormatContext->nb_streams; i++) { var stream = FFmpegStream.Create(pFormatContext->streams[i], this); streams.Add(stream); } pDecodedFrame = ffmpeg.av_frame_alloc(); if (pDecodedFrame == null) { throw new ApplicationException("Couldn't allocate a frame for decoding."); } pCpuCopyFrame = ffmpeg.av_frame_alloc(); if (pCpuCopyFrame == null) { throw new ApplicationException("Couldn't allocate a frame for hardware decoding."); } // dispose cached video image from previous file ClearStreamInfo(); }
/// <summary> /// Initializes the internal transcoder -- This create the input, processing, and output blocks that make /// up the video and audio decoding stream. /// </summary> /// <param name="filePath">The file path.</param> /// <param name="inputFormatName">Name of the input format. Leave null or empty to detect automatically</param> /// <param name="referer">The referer. Leave null or empty to skip setting it</param> /// <param name="userAgent">The user agent. Leave null or empty to skip setting it.</param> /// <exception cref="FileFormatException"></exception> /// <exception cref="Exception">Could not find stream info /// or /// Media must contain at least a video or and audio stream</exception> /// <exception cref="System.Exception">Could not open file /// or /// Could not find stream info /// or /// Media must contain a video stream /// or /// Media must contain an audio stream /// or /// Unsupported codec /// or /// Could not initialize the output conversion context /// or /// Could not create output codec context from input /// or /// Could not open codec</exception> private void InitializeMedia(string filePath, string inputFormatName, string referer, string userAgent) { // Create the input format context by opening the file InputFormatContext = ffmpeg.avformat_alloc_context(); AVDictionary* optionsDict = null; if (string.IsNullOrWhiteSpace(userAgent) == false) ffmpeg.av_dict_set(&optionsDict, "user-agent", userAgent, 0); if (string.IsNullOrWhiteSpace(referer) == false) ffmpeg.av_dict_set(&optionsDict, "headers", $"Referer:{referer}", 0); ffmpeg.av_dict_set_int(&optionsDict, "usetoc", 1, 0); { // for m3u8 (HLS) streaming // TODO: maybe detect here if it is streaming? I need to test if this negatively affects filesystem files or network files as opposed to RTSP streams and HLS streams ffmpeg.av_dict_set_int(&optionsDict, "multiple_requests", 1, 0); ffmpeg.av_dict_set_int(&optionsDict, "reconnect", 1, 0); ffmpeg.av_dict_set_int(&optionsDict, "reconnect_at_eof", 1, 0); ffmpeg.av_dict_set_int(&optionsDict, "reconnect_streamed", 1, 0); ffmpeg.av_dict_set_int(&optionsDict, "reconnect_delay_max", (int)Constants.WaitForPlaybackReadyStateTimeout.TotalMilliseconds, 0); } AVInputFormat* inputFormat = null; if (string.IsNullOrWhiteSpace(inputFormatName) == false) inputFormat = ffmpeg.av_find_input_format(inputFormatName); fixed (AVFormatContext** inputFormatContextRef = &InputFormatContext) { if (ffmpeg.avformat_open_input(inputFormatContextRef, filePath, inputFormat, &optionsDict) != 0) throw new FileFormatException(string.Format("Could not open stream or file '{0}'", filePath)); } InputFormatContext->iformat->flags |= ffmpeg.AVFMT_FLAG_NOBUFFER; InputFormatContext->iformat->flags |= ffmpeg.AVFMT_FLAG_NOFILLIN; ffmpeg.av_dict_free(&optionsDict); // Extract the stream info headers from the file if (ffmpeg.avformat_find_stream_info(InputFormatContext, null) != 0) throw new Exception("Could not find stream info"); // search for the audio and video streams for (int i = 0; i < InputFormatContext->nb_streams; i++) { var codecType = InputFormatContext->streams[i]->codec->codec_type; if (codecType == AVMediaType.AVMEDIA_TYPE_VIDEO && InputVideoStream == null) { InputVideoStream = InputFormatContext->streams[i]; continue; } if (codecType == AVMediaType.AVMEDIA_TYPE_AUDIO && InputAudioStream == null) { InputAudioStream = InputFormatContext->streams[i]; continue; } } if (InputVideoStream != null) { this.InitializeVideo(); this.HasVideo = VideoBitrate > 0 || VideoFrameRate > 0M || VideoFrameWidth > 0 || VideoFrameHeight > 0; } if (InputAudioStream != null) { this.InitializeAudio(); this.HasAudio = AudioBytesPerSample > 0; } if (HasAudio == false && HasVideo == false) { throw new Exception("Media must contain at least a video or and audio stream"); } else { // General Properties here NaturalDuration = Convert.ToDecimal(Convert.ToDouble(InputFormatContext->duration) / Convert.ToDouble(ffmpeg.AV_TIME_BASE)); IsLiveStream = Helper.IsNoPtsValue(InputFormatContext->duration); StartTime = Convert.ToDecimal(Convert.ToDouble(InputFormatContext->start_time) / Convert.ToDouble(ffmpeg.AV_TIME_BASE)); EndTime = StartTime + NaturalDuration; RealtimeClock.Seek(StartTime); } }
public MediaFile(String path, bool tryFrames = true) { pFormatCtx = ffmpeg.avformat_alloc_context(); var formatCtx = pFormatCtx; ffmpeg.avformat_open_input(&formatCtx, path, null, null).ThrowExceptionIfError(); ffmpeg.avformat_find_stream_info(pFormatCtx, null).ThrowExceptionIfError(); AVStream *pStream = null; for (var i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO) { pStream = pFormatCtx->streams[i]; break; } } if (pStream == null) { throw new InvalidOperationException("Could not found video stream."); } streamIndex = pStream->index; pCodecCtx = pStream->codec; var codecId = pCodecCtx->codec_id; var pCodec = ffmpeg.avcodec_find_decoder(codecId); if (pCodec == null) { throw new InvalidOperationException("Unsupported codec."); } filepath = path; ffmpeg.avcodec_open2(pCodecCtx, pCodec, null).ThrowExceptionIfError(); CodecName = ffmpeg.avcodec_get_name(codecId); pPacket = ffmpeg.av_packet_alloc(); pFrame = ffmpeg.av_frame_alloc(); width = pCodecCtx->width; height = pCodecCtx->height; totalFrames = tryFrames ? TryGetFrameCount() : pStream->nb_frames; var pixFmt = pCodecCtx->pix_fmt; if (pixFmt == AVPixelFormat.AV_PIX_FMT_NONE) { pixFmt = AVPixelFormat.AV_PIX_FMT_YUV420P; } var destPixFmt = AVPixelFormat.AV_PIX_FMT_BGR24; scaleCtx = ffmpeg.sws_getContext(width, height, pixFmt, width, height, destPixFmt, ffmpeg.SWS_BICUBIC, null, null, null); var rgbBufSize = ffmpeg.av_image_get_buffer_size(destPixFmt, width, height, 1); rgbFrameBuffer = Marshal.AllocHGlobal(rgbBufSize); rgbBuf = new byte_ptrArray4(); dstLinesize = new int_array4(); ffmpeg.av_image_fill_arrays(ref rgbBuf, ref dstLinesize, (byte *)rgbFrameBuffer, destPixFmt, width, height, 1); }
/// <summary> /// Disposes all active objects and opens a file or url /// </summary> /// <param name="url">path of the media file</param> public void OpenFileOrUrl(string url) { this.Dispose(); // Initialize instance of AVUTIL, AVCODEC, AVFORMAT ffmpeg.av_register_all(); ffmpeg.avcodec_register_all(); ffmpeg.avformat_network_init(); // Open source file AVFormatContext* pFormatContext = ffmpeg.avformat_alloc_context(); if (ffmpeg.avformat_open_input(&pFormatContext, url, null, null) != 0) throw new Exception("File or URL not found!"); if (ffmpeg.avformat_find_stream_info(pFormatContext, null) != 0) throw new Exception("No stream information found!"); // Collect general media information this.Filename = new String(pFormatContext->filename); this.Metadata = ToDictionary(pFormatContext->metadata); this.Duration = ToTimeSpan(pFormatContext->duration); this.BitRate = pFormatContext->bit_rate; // Collect information about streams bool isFirstVideoStream = true; for (int i = 0; i < pFormatContext->nb_streams; i++) { #region Read stream information FFmpegStreamInfo info = new FFmpegStreamInfo(); info.AVStream = pFormatContext->streams[i]; info.Index = pFormatContext->streams[i]->index; switch (pFormatContext->streams[i]->codec->codec_type) { case AVMediaType.AVMEDIA_TYPE_VIDEO: info.StreamType = FFmpegStreamType.Video; info.Video_Width = pFormatContext->streams[i]->codec->width; info.Video_Height = pFormatContext->streams[i]->codec->height; info.Video_FPS = ToDouble(pFormatContext->streams[i]->codec->framerate); if (isFirstVideoStream) { this.VideoResolution = new Size(info.Video_Width, info.Video_Height); isFirstVideoStream = false; } break; case AVMediaType.AVMEDIA_TYPE_AUDIO: info.StreamType = FFmpegStreamType.Audio; info.Audio_SampleRate = pFormatContext->streams[i]->codec->sample_rate; info.Audio_Channels = pFormatContext->streams[i]->codec->channels; break; case AVMediaType.AVMEDIA_TYPE_SUBTITLE: info.StreamType = FFmpegStreamType.Subtitle; break; default: info.StreamType = FFmpegStreamType.Unknown; break; } info.MetaData = ToDictionary(pFormatContext->streams[i]->metadata); if (info.MetaData.ContainsKey("language")) info.Language = info.MetaData["language"]; info.BitRate = pFormatContext->streams[i]->codec->bit_rate; info.FourCC = ToFourCCString(pFormatContext->streams[i]->codec->codec_tag); info.CodecName = getAvCodecName(pFormatContext->streams[i]->codec->codec_id); this.Streams.Add(info); #endregion } this.AVFormatContext = pFormatContext; _isDisposed = false; }
public void Open(string FileName) { DecoderConfig.Init(); AVFormatContext* pFormatContext = FFmpegInvoke.avformat_alloc_context(); _pFormatContext = pFormatContext; if (FFmpegInvoke.avformat_open_input(&pFormatContext, FileName, null, null) != 0) throw new Exception("Could not open file"); if (FFmpegInvoke.avformat_find_stream_info(pFormatContext, null) != 0) throw new Exception("Could not find stream info"); for (int i = 0; i < pFormatContext->nb_streams; i++) { if (pFormatContext->streams[i]->codec->codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO) { _pStream = pFormatContext->streams[i]; break; } } if (_pStream == null) throw new Exception("Could not found video stream"); AVCodecContext codecContext = *(_pStream->codec); codecContext.workaround_bugs = FFmpegInvoke.FF_BUG_AUTODETECT; _frameduration = 1 / q2d(_pStream->r_frame_rate); FrameCount = _pStream->nb_frames; Duration = (float)pFormatContext->duration / FFmpegInvoke.AV_TIME_BASE; Width = codecContext.width; Height = codecContext.height; AVPixelFormat sourcePixFmt = codecContext.pix_fmt; AVCodecID codecId = codecContext.codec_id; var convertToPixFmt = AVPixelFormat.AV_PIX_FMT_RGB24; _pConvertContext = FFmpegInvoke.sws_getContext(Width, Height, sourcePixFmt, Width, Height, convertToPixFmt, FFmpegInvoke.SWS_FAST_BILINEAR, null, null, null); if (_pConvertContext == null) throw new Exception("Could not initialize the conversion context"); _pConvertedFrame = (AVPicture*)FFmpegInvoke.avcodec_alloc_frame(); int convertedFrameBufferSize = FFmpegInvoke.avpicture_get_size(convertToPixFmt, Width, Height); _pConvertedFrameBuffer = (byte*)FFmpegInvoke.av_malloc((uint)convertedFrameBufferSize); FFmpegInvoke.avpicture_fill(_pConvertedFrame, _pConvertedFrameBuffer, convertToPixFmt, Width, Height); AVCodec* pCodec = FFmpegInvoke.avcodec_find_decoder(codecId); if (pCodec == null) throw new Exception("Unsupported codec"); if (FFmpegInvoke.avcodec_open2(_pStream->codec, pCodec, null) < 0) throw new Exception("Could not open codec"); _pDecodedFrame = FFmpegInvoke.avcodec_alloc_frame(); _packet = new AVPacket(); fixed (AVPacket* pPacket = &_packet) { FFmpegInvoke.av_init_packet(pPacket); } _opened = true; }
public void Close() { if (!_opened) return; FFmpegInvoke.av_free(_pConvertedFrame); FFmpegInvoke.av_free(_pConvertedFrameBuffer); FFmpegInvoke.sws_freeContext(_pConvertContext); FFmpegInvoke.av_free(_pDecodedFrame); FFmpegInvoke.avcodec_close(_pStream->codec); fixed (AVFormatContext** pFormatContext = &_pFormatContext) { FFmpegInvoke.avformat_close_input(pFormatContext); } _videoClock = 0; _pFormatContext = null; _pStream = null; _pDecodedFrame = null; _pConvertedFrame = null; _pConvertedFrameBuffer = null; _pConvertContext = null; _opened = false; }
public void CreateOutput() { AVFormatContext *outputFmtCtx; AudioIndex = -1; VideoIndex = -1; string filename = @"C:\Users\admin\Desktop\output223423423.avi"; AVFormatContext *inputFmtCtx = _fmt_ctx; if (ffmpeg.avformat_alloc_output_context2(&outputFmtCtx, null, null, filename) < 0) //음수가 나오면 에러인거야... { Console.WriteLine("파일 생성 못해!!!"); } var oCodec = ffmpeg.avcodec_find_encoder(AVCodecID.AV_CODEC_ID_H264); for (int index = 0; index < inputFmtCtx->nb_streams; index++) { AVStream * in_stream = inputFmtCtx->streams[index]; AVCodecContext *in_codec_ctx = in_stream->codec; in_codec_ctx = ffmpeg.avcodec_alloc_context3(inputFmtCtx->data_codec); AVStream *out_stream = ffmpeg.avformat_new_stream(outputFmtCtx, null); if (out_stream == null) { Console.WriteLine("OUTPUT 스트림 NULL"); } // AVCodecContext *outCodecContext = out_stream->codec; outCodecContext->codec = oCodec; outCodecContext = ffmpeg.avcodec_alloc_context3(oCodec); outCodecContext->height = 500; outCodecContext->width = 600; // outCodecContext->sample_aspect_ratio = videoInfo.Sample_aspect_ratio; outCodecContext->pix_fmt = AVPixelFormat.AV_PIX_FMT_YUV420P; outCodecContext->time_base = new AVRational { num = 1, den = 15 }; // outCodecContext->framerate = ffmpeg.av_inv_q(videoInfo.Framerate); //context를 설정해야 뭔가 쓸수잇오..... if (ffmpeg.avcodec_parameters_from_context(out_stream->codecpar, outCodecContext) < 0) { Console.WriteLine("copy 못해에!!!"); } out_stream->time_base = in_stream->time_base; outCodecContext->codec_tag = 0; if ((outputFmtCtx->oformat->flags & ffmpeg.AVFMT_GLOBALHEADER) == 0) { outCodecContext->flags |= ffmpeg.AV_CODEC_FLAG_GLOBAL_HEADER; } // ffmpeg.avcodec_open2(outCodecContext, oCodec, null).ThrowExceptionIfError(); VideoIndex = 0; AudioIndex = 1; ffmpeg.av_dump_format(outputFmtCtx, 0, filename, 1); if ((outputFmtCtx->oformat->flags & ffmpeg.AVFMT_NOFILE) == 0) { // This actually open the file if (ffmpeg.avio_open(&outputFmtCtx->pb, filename, ffmpeg.AVIO_FLAG_WRITE) < 0) { Console.WriteLine("못만들오..."); } } if (ffmpeg.avformat_write_header(outputFmtCtx, null) < 0) { Console.WriteLine("헤더를 못써...\n"); } } ffmpeg.av_write_trailer(outputFmtCtx); ffmpeg.avio_closep(&outputFmtCtx->pb); ffmpeg.avformat_free_context(outputFmtCtx); }
private InputContainer(AVFormatContext *formatContext) : base(formatContext) { }
/// <summary> /// Releases all managed and unmanaged resources /// </summary> public void Dispose() { if (IsCancellationPending) return; this.IsCancellationPending = true; this.VideoRenderTimer.Stop(); if (this.AudioRenderer != null) { if (this.AudioRenderer.HasInitialized) this.AudioRenderer.Stop(); this.AudioRenderer.Dispose(); this.AudioRenderer = null; } if (MediaFrameExtractorThread != null) { MediaFrameExtractorThread.Join(); MediaFrameExtractorThread = null; } if (MediaFramesExtractedDone != null) { try { MediaFramesExtractedDone.Dispose(); MediaFramesExtractedDone = null; } finally { } } if (PrimaryFramesCache != null) { PrimaryFramesCache.Clear(); PrimaryFramesCache = null; } if (SecondaryFramesCache != null) { SecondaryFramesCache.Clear(); SecondaryFramesCache = null; } if (VideoCodecContext != null) { fixed (AVCodecContext** videoCodecContextRef = &VideoCodecContext) { ffmpeg.avcodec_close(VideoCodecContext); ffmpeg.avcodec_free_context(videoCodecContextRef); VideoCodecContext = null; } } if (AudioCodecContext != null) { fixed (AVCodecContext** audioCodecContextRef = &AudioCodecContext) { ffmpeg.avcodec_close(AudioCodecContext); ffmpeg.avcodec_free_context(audioCodecContextRef); AudioCodecContext = null; } } if (VideoResampler != null) { ffmpeg.sws_freeContext(VideoResampler); VideoResampler = null; } if (AudioResampler != null) { fixed (SwrContext** audioResamplerRef = &AudioResampler) { ffmpeg.swr_close(AudioResampler); ffmpeg.swr_free(audioResamplerRef); AudioResampler = null; } } if (InputFormatContext != null) { fixed (AVFormatContext** inputFormatContextRef = &InputFormatContext) { ffmpeg.avformat_close_input(inputFormatContextRef); ffmpeg.avformat_free_context(InputFormatContext); InputFormatContext = null; } } if (DecodedPictureHolder != null) { ffmpeg.av_free(DecodedPictureHolder); DecodedPictureHolder = null; } if (DecodedWaveHolder != null) { ffmpeg.av_free(DecodedWaveHolder); DecodedWaveHolder = null; } }
public void testSet() { FFmpegBinariesHelper.RegisterFFmpegBinaries(); ffmpeg.avdevice_register_all(); var fmt_ctx = _fmt_ctx; fmt_ctx = ffmpeg.avformat_alloc_context(); AVInputFormat *iformat = ffmpeg.av_find_input_format("dshow"); string device = "video=USB3. 0 capture:audio=디지털 오디오 인터페이스(5- USB3. 0 capture)"; var a = ffmpeg.avformat_open_input(&fmt_ctx, device, iformat, null); //음수이면 파일 안열려..그런 장치 없어!! var b = ffmpeg.avformat_find_stream_info(fmt_ctx, null); //Stream을 찾을수 없어... int videoIndex = -1; int audioIndex = -1; _fmt_ctx = fmt_ctx; AVFormatContext *outputFmtCtx; AudioIndex = -1; VideoIndex = -1; string filename = @"C:\Users\admin\Desktop\output223423423.avi"; AVFormatContext *inputFmtCtx = _fmt_ctx; if (ffmpeg.avformat_alloc_output_context2(&outputFmtCtx, null, null, filename) < 0) //음수가 나오면 에러인거야... { Console.WriteLine("파일 생성 못해!!!"); } var oCodec = ffmpeg.avcodec_find_encoder(AVCodecID.AV_CODEC_ID_MPEG4); for (int index = 0; index < inputFmtCtx->nb_streams; index++) { AVStream * in_stream = inputFmtCtx->streams[index]; AVCodecContext *in_codec_ctx = in_stream->codec; in_codec_ctx = ffmpeg.avcodec_alloc_context3(inputFmtCtx->data_codec); AVStream *out_stream = ffmpeg.avformat_new_stream(outputFmtCtx, null); if (out_stream == null) { Console.WriteLine("OUTPUT 스트림 NULL"); } // AVCodecContext *outCodecContext = out_stream->codec; outCodecContext->codec = oCodec; outCodecContext = ffmpeg.avcodec_alloc_context3(oCodec); outCodecContext->height = 500; outCodecContext->width = 600; // outCodecContext->sample_aspect_ratio = videoInfo.Sample_aspect_ratio; outCodecContext->pix_fmt = AVPixelFormat.AV_PIX_FMT_YUV420P; outCodecContext->time_base = new AVRational { num = 1, den = 15 }; // outCodecContext->framerate = ffmpeg.av_inv_q(videoInfo.Framerate); //context를 설정해야 뭔가 쓸수잇오..... if (ffmpeg.avcodec_parameters_from_context(out_stream->codecpar, outCodecContext) < 0) { Console.WriteLine("copy 못해에!!!"); } out_stream->time_base = in_stream->time_base; outCodecContext->codec_tag = 0; if ((outputFmtCtx->oformat->flags & ffmpeg.AVFMT_GLOBALHEADER) == 0) { outCodecContext->flags |= ffmpeg.AV_CODEC_FLAG_GLOBAL_HEADER; } // ffmpeg.avcodec_open2(outCodecContext, oCodec, null).ThrowExceptionIfError(); VideoIndex = 0; AudioIndex = 1; ffmpeg.av_dump_format(outputFmtCtx, 0, filename, 1); if ((outputFmtCtx->oformat->flags & ffmpeg.AVFMT_NOFILE) == 0) { // This actually open the file if (ffmpeg.avio_open(&outputFmtCtx->pb, filename, ffmpeg.AVIO_FLAG_WRITE) < 0) { Console.WriteLine("못만들오..."); } } if (ffmpeg.avformat_write_header(outputFmtCtx, null) < 0) { Console.WriteLine("헤더를 못써...\n"); } } //ffmpeg.av_write_trailer(outputFmtCtx); //ffmpeg.avio_closep(&outputFmtCtx->pb); //ffmpeg.avformat_free_context(outputFmtCtx); //nb_streams : 요소 몇갠지..!!! 내가 찾은거에서 뭐있는지 for (int index = 0; index < fmt_ctx->nb_streams; index++) { var avCodecContext = fmt_ctx->streams[index]->codec; if (avCodecContext->codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO) { videoIndex = index; } else if (avCodecContext->codec_type == AVMediaType.AVMEDIA_TYPE_AUDIO) { audioIndex = index; Console.WriteLine(audioIndex + "***"); } if (avCodecContext->codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO) { videoIndex = index; Console.WriteLine($"====================={avCodecContext->codec_type}======================"); //Console.WriteLine(avCodecContext->bit_rate); //W * H *FPS //Console.WriteLine(avCodecContext->codec_id); //Console.WriteLine(avCodecContext->width); //Console.WriteLine(avCodecContext->coded_width); //Console.WriteLine(avCodecContext->height); //Console.WriteLine(avCodecContext->coded_height); //Console.WriteLine(avCodecContext->pts_correction_num_faulty_pts); //Console.WriteLine(avCodecContext->pts_correction_last_dts); //Console.WriteLine(avCodecContext->pts_correction_last_pts); Console.WriteLine(); } else if (avCodecContext->codec_type == AVMediaType.AVMEDIA_TYPE_AUDIO) { audioIndex = index; Console.WriteLine($"====================={avCodecContext->codec_type}======================"); //Console.WriteLine(avCodecContext->bit_rate); //W * H *FPS //Console.WriteLine(avCodecContext->codec_id); //Console.WriteLine($"Channels : {avCodecContext->channels}"); //Console.WriteLine(avCodecContext->width); //Console.WriteLine(avCodecContext->coded_width); //Console.WriteLine(avCodecContext->height); //Console.WriteLine(avCodecContext->coded_height); //Console.WriteLine(avCodecContext->pts_correction_num_faulty_pts); //Console.WriteLine(avCodecContext->pts_correction_last_dts); //Console.WriteLine(avCodecContext->pts_correction_last_pts); } } int ret; AVPacket pkt; int out_stream_index; while (true) { ret = ffmpeg.av_read_frame(fmt_ctx, &pkt); //ret == 0 이면 if (ret == ffmpeg.AVERROR_EOF) { Console.WriteLine("frame end"); break; } if (pkt.stream_index == videoIndex) { Console.WriteLine("Video Packet"); } else if (pkt.stream_index == audioIndex) { Console.WriteLine("Audio Packet"); } AVStream *in_stream = fmt_ctx->streams[pkt.stream_index]; out_stream_index = (pkt.stream_index == videoIndex) ? videoIndex : audioIndex; AVStream *out_stream = outputFmtCtx->streams[out_stream_index]; ffmpeg.av_packet_rescale_ts(&pkt, in_stream->time_base, out_stream->time_base); pkt.stream_index = out_stream_index; if (ffmpeg.av_interleaved_write_frame(outputFmtCtx, &pkt) < 0) { Console.WriteLine("!!!!!!!!@#####!@#!@#!"); break; } ffmpeg.av_packet_unref(&pkt); //옛날엔 av_free_packet() } ffmpeg.av_write_trailer(outputFmtCtx); }
public static extern void avdevice_capabilities_free(AVDeviceCapabilitiesQuery ** @caps, AVFormatContext * @s);
public unsafe H264Decoder(List <byte[]> nalUnits) { if (!initialized) { ffmpeg.av_register_all(); initialized = true; } int localStreamSuffix = streamSuffix; streamSuffix++; int dataSize = 0; foreach (byte[] nalUnit in nalUnits) { dataSize += nalUnit.Length + startSequence.Length; } byte *dat = (byte *)ffmpeg.av_malloc((ulong)dataSize); fixed(byte *start = startSequence) { foreach (byte[] nalUnit in nalUnits) { fixed(byte *dataPtr = nalUnit) { UnmanagedMemory.CopyMemory(dat, start, (uint)startSequence.Length); dat += startSequence.Length; UnmanagedMemory.CopyMemory(dat, dataPtr, (uint)nalUnit.Length); dat += nalUnit.Length; } } dat -= dataSize; } AVFormatContext *icLocal = ffmpeg.avformat_alloc_context(); ic = icLocal; avio_alloc_context_write_packet_func writeCallback; writeCallback.Pointer = IntPtr.Zero; avio_alloc_context_seek_func seekCallback; seekCallback.Pointer = IntPtr.Zero; avio_alloc_context_read_packet_func readCallback; readCallback.Pointer = IntPtr.Zero; icLocal->pb = ffmpeg.avio_alloc_context(dat, bufferSize, 0, null, readCallback, writeCallback, seekCallback); if (icLocal->pb == null) { throw new Exception("Failed to allocate ffmpeg context."); } // Need to probe buffer for input format unless you already know it AVProbeData probe_data; probe_data.buf_size = dataSize; probe_data.filename = (byte *)Marshal.StringToHGlobalAnsi($"stream_{localStreamSuffix}"); probe_data.buf = (byte *)UnmanagedMemory.Alloc(probe_data.buf_size); UnmanagedMemory.CopyMemory(probe_data.buf, dat, (uint)probe_data.buf_size); AVInputFormat *pAVInputFormat = ffmpeg.av_probe_input_format(&probe_data, 1); if (pAVInputFormat == null) { pAVInputFormat = ffmpeg.av_probe_input_format(&probe_data, 0); } // cleanup UnmanagedMemory.DeAlloc((IntPtr)probe_data.buf, probe_data.buf_size); probe_data.buf = null; pAVInputFormat->flags |= ffmpeg.AVFMT_NOFILE; ffmpeg.avformat_open_input(&icLocal, $"stream_{localStreamSuffix}", pAVInputFormat, null); for (int i = 0; i < icLocal->nb_streams; i++) { AVCodecContext *enc = icLocal->streams[i]->codec; if (AVMediaType.AVMEDIA_TYPE_VIDEO == enc->codec_type) { AVCodec *codec = ffmpeg.avcodec_find_decoder(enc->codec_id); if (codec == null || ffmpeg.avcodec_open2(enc, codec, null) < 0) { //Console.WriteLine("Cannot find codec"); } video_st = icLocal->streams[i]; } } //Init picture yuv_image = ffmpeg.av_frame_alloc(); yuv_image->format = -1; //We do not know the format of the raw decoded image }
public static extern int avdevice_list_devices(AVFormatContext * @s, AVDeviceInfoList ** @device_list);
public int Init(string fileName, System.Windows.Controls.Image image, System.Windows.Controls.Image Dimage, System.Windows.Controls.Label startTime, System.Windows.Controls.Slider slider, System.Windows.Controls.Slider slider2) { ffmpeg.avcodec_register_all(); AVFormatContext *pFormatCtx; pFormatCtx = ffmpeg.avformat_alloc_context(); this.pFormatCtx = pFormatCtx; ffmpeg.avformat_open_input(&pFormatCtx, fileName, null, null); ffmpeg.avformat_find_stream_info(pFormatCtx, null); for (int i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO) { videoIndex = i; Console.WriteLine("video.............." + videoIndex); } if (pFormatCtx->streams[i]->codec->codec_type == AVMediaType.AVMEDIA_TYPE_AUDIO) { audioIndex = i; Console.WriteLine("audio.............." + audioIndex); } } if (videoIndex == -1) { Console.WriteLine("Couldn't find a video stream."); return(-1); } if (audioIndex == -1) { Console.WriteLine("Couldn't find a audio stream."); return(-1); } if (videoIndex > -1) { pCodecCtxVideo = pFormatCtx->streams[videoIndex]->codec; pCodecVideo = ffmpeg.avcodec_find_decoder(pCodecCtxVideo->codec_id); if (pCodecVideo == null) { return(-1); } pCodecCtxVideo->codec_id = pCodecVideo->id; pCodecCtxVideo->lowres = 0; if (pCodecCtxVideo->lowres > pCodecVideo->max_lowres) { pCodecCtxVideo->lowres = pCodecVideo->max_lowres; } pCodecCtxVideo->idct_algo = ffmpeg.FF_IDCT_AUTO; pCodecCtxVideo->error_concealment = 3; if (ffmpeg.avcodec_open2(pCodecCtxVideo, pCodecVideo, null) < 0) { return(-1); } Console.WriteLine("Find a video stream. channel = " + videoIndex); frameSize = new System.Windows.Size(pCodecCtxVideo->width, pCodecCtxVideo->height); double frameRate = ffmpeg.av_q2d(pFormatCtx->streams[videoIndex]->r_frame_rate); frameGap = (int)(1000 / frameRate); double frameWidth = frameSize.Width; double frameHeight = frameSize.Height; //fsrcnn = FSRCNN_construct(); //FSRCNN_init(fsrcnn, (int)frameHeight, (int)frameWidth); image.Dispatcher.BeginInvoke((Action)(() => { slider2.Visibility = System.Windows.Visibility.Visible; if (frameWidth >= 1000) { ((MainWindow)System.Windows.Application.Current.MainWindow).WindowState = WindowState.Maximized; double tempRate = ((MainWindow)System.Windows.Application.Current.MainWindow).Width / frameWidth; frameWidth = ((MainWindow)System.Windows.Application.Current.MainWindow).Width; frameHeight *= tempRate; } ((MainWindow)System.Windows.Application.Current.MainWindow).Width = frameWidth; ((MainWindow)System.Windows.Application.Current.MainWindow).Height = frameHeight + 140; image.Width = frameWidth; image.Height = frameHeight; Dimage.Width = frameWidth; Dimage.Height = frameHeight; grid3.Width = frameWidth; grid.Width = frameWidth; grid2.Width = frameWidth; slider.Width = frameWidth - 140; slider2.Width = frameWidth - 140; if (initCheck == false) { originalHeight = ((MainWindow)System.Windows.Application.Current.MainWindow).Height; originalWidth = ((MainWindow)System.Windows.Application.Current.MainWindow).Width; ((MainWindow)System.Windows.Application.Current.MainWindow).Width = 800; ((MainWindow)System.Windows.Application.Current.MainWindow).Height = 800 * (originalHeight / originalWidth); } ((MainWindow)System.Windows.Application.Current.MainWindow).SizeChanged += new SizeChangedEventHandler(Window_SizeChanged); })); pFrameVideo = ffmpeg.av_frame_alloc(); swsCtxVideo = new SwsContext *[4]; for (int i = 0; i < scalerNum; i++) { swsCtxVideo[i] = ffmpeg.sws_getContext( (int)frameSize.Width, (int)frameSize.Height, pCodecCtxVideo->pix_fmt, (int)frameSize.Width, (int)frameSize.Height, AVPixelFormat.AV_PIX_FMT_BGR24, ffmpeg.SWS_FAST_BILINEAR, null, null, null); } } if (audioIndex > -1) { pCodecAudio = ffmpeg.avcodec_find_decoder(pFormatCtx->streams[audioIndex]->codecpar->codec_id); pCodeCtxAudio = ffmpeg.avcodec_alloc_context3(pCodecAudio); ffmpeg.avcodec_parameters_to_context(pCodeCtxAudio, pFormatCtx->streams[audioIndex]->codecpar); if (pCodecAudio == null) { return(-1); } if (ffmpeg.avcodec_open2(pCodeCtxAudio, pCodecAudio, null) < 0) { return(-1); } Console.WriteLine("Find a audio stream. channel = " + audioIndex); sdlAudio = new SDLAudio(); sdlAudio.SDL_Init(pCodeCtxAudio); pFrameAudio = ffmpeg.av_frame_alloc(); swrCtxAudio = ffmpeg.swr_alloc(); ffmpeg.av_opt_set_channel_layout(swrCtxAudio, "in_channel_layout", (long)pCodeCtxAudio->channel_layout, 0); ffmpeg.av_opt_set_channel_layout(swrCtxAudio, "out_channel_layout", (long)pCodeCtxAudio->channel_layout, 0); ffmpeg.av_opt_set_int(swrCtxAudio, "in_sample_rate", pCodeCtxAudio->sample_rate, 0); ffmpeg.av_opt_set_int(swrCtxAudio, "out_sample_rate", pCodeCtxAudio->sample_rate, 0); ffmpeg.av_opt_set_sample_fmt(swrCtxAudio, "in_sample_fmt", pCodeCtxAudio->sample_fmt, 0); ffmpeg.av_opt_set_sample_fmt(swrCtxAudio, "out_sample_fmt", AVSampleFormat.AV_SAMPLE_FMT_FLT, 0); ffmpeg.swr_init(swrCtxAudio); } this.image = image; this.Dimage = Dimage; entirePlayTime = pFormatCtx->duration; this.startTime = startTime; this.slider = slider; scalerId = 0; rasterId = 0; videoPool = new PacketPool(); audioPool = new PacketPool(); fPool = new FrameBuffer(frameSize); isEOF = false; state = State.Init; decodeSeek = false; srSeek = false; drawSeek = false; scaleSeek = new bool[scalerNum]; for (int i = 0; i < scalerNum; i++) { scaleSeek[i] = false; } rasterSeek = new bool[rasterNum]; for (int i = 0; i < rasterNum; i++) { rasterSeek[i] = false; } gmfn = new GMFN(); return(0); }
private void Open(string fileName, int width, int height, AVCodecID videoCodec, int framerate, AVCodecID audioCodec) { CreatedDate = DateTime.UtcNow; Filename = fileName; _abort = false; _ignoreAudio = false; if (videoCodec != AVCodecID.AV_CODEC_ID_NONE) { IsTimelapse = framerate != 0; if (((width & 1) != 0) || ((height & 1) != 0)) { throw new ArgumentException("Video file resolution must be a multiple of two."); } } int i; _lastPacket = DateTime.UtcNow; var outputFormat = ffmpeg.av_guess_format(null, fileName, null); if (outputFormat == null) { switch (videoCodec) { default: case AVCodecID.AV_CODEC_ID_MPEG1VIDEO: outputFormat = ffmpeg.av_guess_format("mpeg1video", null, null); break; } } _formatContext = ffmpeg.avformat_alloc_context(); if (_formatContext == null) { throw new Exception("Cannot allocate format context."); } _interruptCallback = InterruptCb; _interruptCallbackAddress = Marshal.GetFunctionPointerForDelegate(_interruptCallback); _formatContext->interrupt_callback.callback = _interruptCallbackAddress; _formatContext->interrupt_callback.opaque = null; _formatContext->oformat = outputFormat; AVDictionary *opts = null; if (audioCodec != AVCodecID.AV_CODEC_ID_NONE) { AddAudioStream(audioCodec); OpenAudio(); } if (videoCodec != AVCodecID.AV_CODEC_ID_NONE) { _width = width; _height = height; //_bitRate = videoBitRate; _framerate = framerate; _isConstantFramerate = framerate > 0; AddVideoStream(videoCodec); OpenVideo(); if (videoCodec == AVCodecID.AV_CODEC_ID_MPEG1VIDEO) { ffmpeg.av_dict_set(&opts, "pkt_size", "1316", 0); ffmpeg.av_dict_set(&opts, "buffer_size", "65535", 0); //ffmpeg.av_dict_set(&opts, "crf", "30", 0); } } if (movflags != "") { ffmpeg.av_dict_set(&opts, "movflags", movflags, 0); } if ((outputFormat->flags & ffmpeg.AVFMT_NOFILE) != ffmpeg.AVFMT_NOFILE) { i = ffmpeg.avio_open2(&_formatContext->pb, fileName, ffmpeg.AVIO_FLAG_WRITE, null, &opts); if (i < 0) { throw new Exception("Cannot create the video file. (" + i + ")"); } } i = ffmpeg.avformat_write_header(_formatContext, null); if (i < 0) { throw new Exception("Cannot write header - check disk space (" + i + ")"); } ffmpeg.av_dict_free(&opts); _frameNumber = 0; _recordingStartTime = DateTime.UtcNow; _opened = true; }
// sets up libavformat state: creates the AVFormatContext, the frames, etc. to start decoding, but does not actually start the decodingLoop private void prepareDecoding() { const int context_buffer_size = 4096; // the first call to FFmpeg will throw an exception if the libraries cannot be found // this will be safely handled in StartDecoding() var fcPtr = ffmpeg.avformat_alloc_context(); formatContext = fcPtr; contextBuffer = (byte *)ffmpeg.av_malloc(context_buffer_size); managedContextBuffer = new byte[context_buffer_size]; readPacketCallback = readPacket; seekCallback = streamSeekCallbacks; formatContext->pb = ffmpeg.avio_alloc_context(contextBuffer, context_buffer_size, 0, (void *)handle.Handle, readPacketCallback, null, seekCallback); int openInputResult = ffmpeg.avformat_open_input(&fcPtr, "dummy", null, null); inputOpened = openInputResult >= 0; if (!inputOpened) { throw new InvalidOperationException($"Error opening file or stream: {getErrorMessage(openInputResult)}"); } int findStreamInfoResult = ffmpeg.avformat_find_stream_info(formatContext, null); if (findStreamInfoResult < 0) { throw new InvalidOperationException($"Error finding stream info: {getErrorMessage(findStreamInfoResult)}"); } var nStreams = formatContext->nb_streams; for (var i = 0; i < nStreams; ++i) { stream = formatContext->streams[i]; codecParams = *stream->codecpar; if (codecParams.codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO) { duration = stream->duration <= 0 ? formatContext->duration : stream->duration; timeBaseInSeconds = stream->time_base.GetValue(); var codecPtr = ffmpeg.avcodec_find_decoder(codecParams.codec_id); if (codecPtr == null) { throw new InvalidOperationException($"Couldn't find codec with id: {codecParams.codec_id}"); } int openCodecResult = ffmpeg.avcodec_open2(stream->codec, codecPtr, null); if (openCodecResult < 0) { throw new InvalidOperationException($"Error trying to open codec with id {codecParams.codec_id}: {getErrorMessage(openCodecResult)}"); } break; } } prepareFilters(); }
public void Close() { try { Program.FfmpegMutex.WaitOne(); _recordingEndTime = DateTime.UtcNow; if (_formatContext != null) { if (!IsStreaming) { if (_opened) { Flush(); } if (_formatContext->pb != null) { ffmpeg.av_write_trailer(_formatContext); } } if (_formatContext->pb != null) { var pinprt = &(_formatContext->pb); ffmpeg.avio_closep(pinprt); _formatContext->pb = null; } _audioBuffer = null; if (_videoFrame != null) { ffmpeg.avpicture_free((AVPicture *)_videoFrame); fixed(AVFrame **pinprt = &(_videoFrame)) { ffmpeg.av_frame_free(pinprt); _videoFrame = null; } } if (_audioFrame != null) { fixed(AVFrame **pinprt = &(_audioFrame)) { ffmpeg.av_frame_free(pinprt); _audioFrame = null; } } if (_videoCodecContext != null) { ffmpeg.avcodec_close(_videoCodecContext); fixed(AVCodecContext **c = &_videoCodecContext) { ffmpeg.avcodec_free_context(c); } } if (_audioCodecContext != null) { ffmpeg.avcodec_close(_audioCodecContext); fixed(AVCodecContext **c = &_audioCodecContext) { ffmpeg.avcodec_free_context(c); } } if (_formatContext->streams != null) { int j = (int)_formatContext->nb_streams; for (var i = j - 1; i >= 0; i--) { AVStream *stream = _formatContext->streams[i]; if (stream != null && stream->codec != null && stream->codec->codec != null) { stream->discard = AVDiscard.AVDISCARD_ALL; ffmpeg.av_freep(&stream); } } } _videoStream = null; _audioStream = null; fixed(AVFormatContext **pinprt = &(_formatContext)) { ffmpeg.av_freep(pinprt); } _formatContext = null; } if (_swsContext != null) { ffmpeg.sws_freeContext(_swsContext); _swsContext = null; } if (_swrContext != null) { ffmpeg.swr_close(_swrContext); _swrContext = null; } try { FileInfo fi = new FileInfo(Filename); SizeBytes = fi.Length; } catch { SizeBytes = 0; } _opened = false; } finally { try { Program.FfmpegMutex.ReleaseMutex(); } catch { } } }
private void ReadFrames() { AVFrame * pConvertedFrame = null; sbyte * pConvertedFrameBuffer = null; SwsContext *pConvertContext = null; BufferedWaveProvider waveProvider = null; SampleChannel sampleChannel = null; bool audioInited = false; bool videoInited = false; var packet = new AVPacket(); do { ffmpeg.av_init_packet(&packet); AVFrame *frame = ffmpeg.av_frame_alloc(); ffmpeg.av_frame_unref(frame); if (ffmpeg.av_read_frame(_formatContext, &packet) < 0) { _stopReadingFrames = true; _res = ReasonToFinishPlaying.VideoSourceError; break; } if ((packet.flags & ffmpeg.AV_PKT_FLAG_CORRUPT) == ffmpeg.AV_PKT_FLAG_CORRUPT) { break; } AVPacket packetTemp = packet; var nf = NewFrame; var da = DataAvailable; _lastPacket = DateTime.UtcNow; if (_audioStream != null && packetTemp.stream_index == _audioStream->index) { if (HasAudioStream != null) { HasAudioStream?.Invoke(this, EventArgs.Empty); HasAudioStream = null; } if (da != null) { int s = 0; var buffer = new sbyte[_audioCodecContext->sample_rate * 2]; var tbuffer = new sbyte[_audioCodecContext->sample_rate * 2]; bool b = false; fixed(sbyte **outPtrs = new sbyte *[32]) { fixed(sbyte *bPtr = &tbuffer[0]) { outPtrs[0] = bPtr; do { int gotFrame = 0; int inUsed = ffmpeg.avcodec_decode_audio4(_audioCodecContext, frame, &gotFrame, &packetTemp); if (inUsed < 0 || gotFrame == 0) { b = true; break; } int numSamplesOut = ffmpeg.swr_convert(_swrContext, outPtrs, _audioCodecContext->sample_rate, &frame->data0, frame->nb_samples); var l = numSamplesOut * 2 * _audioCodecContext->channels; Buffer.BlockCopy(tbuffer, 0, buffer, s, l); s += l; packetTemp.data += inUsed; packetTemp.size -= inUsed; } while (packetTemp.size > 0); } } if (b) { break; } ffmpeg.av_free_packet(&packet); ffmpeg.av_frame_free(&frame); if (!audioInited) { audioInited = true; RecordingFormat = new WaveFormat(_audioCodecContext->sample_rate, 16, _audioCodecContext->channels); waveProvider = new BufferedWaveProvider(RecordingFormat) { DiscardOnBufferOverflow = true, BufferDuration = TimeSpan.FromMilliseconds(500) }; sampleChannel = new SampleChannel(waveProvider); sampleChannel.PreVolumeMeter += SampleChannelPreVolumeMeter; } byte[] ba = new byte[s]; Buffer.BlockCopy(buffer, 0, ba, 0, s); waveProvider.AddSamples(ba, 0, s); var sampleBuffer = new float[s]; int read = sampleChannel.Read(sampleBuffer, 0, s); da(this, new DataAvailableEventArgs(ba, read)); if (Listening) { WaveOutProvider?.AddSamples(ba, 0, read); } } } if (nf != null && _videoStream != null && packet.stream_index == _videoStream->index) { int frameFinished = 0; //decode video frame int ret = ffmpeg.avcodec_decode_video2(_codecContext, frame, &frameFinished, &packetTemp); if (ret < 0) { ffmpeg.av_free_packet(&packet); ffmpeg.av_frame_free(&frame); break; } if (frameFinished == 1) { if (!videoInited) { videoInited = true; pConvertedFrame = ffmpeg.av_frame_alloc(); var convertedFrameBufferSize = ffmpeg.avpicture_get_size(AVPixelFormat.AV_PIX_FMT_BGR24, _codecContext->width, _codecContext->height); pConvertedFrameBuffer = (sbyte *)ffmpeg.av_malloc((ulong)convertedFrameBufferSize); ffmpeg.avpicture_fill((AVPicture *)pConvertedFrame, pConvertedFrameBuffer, AVPixelFormat.AV_PIX_FMT_BGR24, _codecContext->width, _codecContext->height); pConvertContext = ffmpeg.sws_getContext(_codecContext->width, _codecContext->height, _codecContext->pix_fmt, _codecContext->width, _codecContext->height, AVPixelFormat.AV_PIX_FMT_BGR24, ffmpeg.SWS_FAST_BILINEAR, null, null, null); } var src = &frame->data0; var dst = &pConvertedFrame->data0; var srcStride = frame->linesize; var dstStride = pConvertedFrame->linesize; ffmpeg.sws_scale(pConvertContext, src, srcStride, 0, _codecContext->height, dst, dstStride); var convertedFrameAddress = pConvertedFrame->data0; if (convertedFrameAddress != null) { var imageBufferPtr = new IntPtr(convertedFrameAddress); var linesize = dstStride[0]; if (frame->decode_error_flags > 0) { ffmpeg.av_free_packet(&packet); ffmpeg.av_frame_free(&frame); break; } using ( var mat = new Bitmap(_codecContext->width, _codecContext->height, linesize, PixelFormat.Format24bppRgb, imageBufferPtr)) { var nfe = new NewFrameEventArgs((Bitmap)mat.Clone()); nf.Invoke(this, nfe); } _lastVideoFrame = DateTime.UtcNow; } } } if (_videoStream != null) { if ((DateTime.UtcNow - _lastVideoFrame).TotalMilliseconds > _timeout) { _res = ReasonToFinishPlaying.DeviceLost; _stopReadingFrames = true; } } ffmpeg.av_free_packet(&packet); ffmpeg.av_frame_free(&frame); } while (!_stopReadingFrames && !MainForm.ShuttingDown); try { Program.FfmpegMutex.WaitOne(); if (pConvertedFrame != null) { ffmpeg.av_free(pConvertedFrame); } if (pConvertedFrameBuffer != null) { ffmpeg.av_free(pConvertedFrameBuffer); } if (_formatContext != null) { if (_formatContext->streams != null) { int j = (int)_formatContext->nb_streams; for (var i = j - 1; i >= 0; i--) { AVStream *stream = _formatContext->streams[i]; if (stream != null && stream->codec != null && stream->codec->codec != null) { stream->discard = AVDiscard.AVDISCARD_ALL; ffmpeg.avcodec_close(stream->codec); } } } fixed(AVFormatContext **f = &_formatContext) { ffmpeg.avformat_close_input(f); } _formatContext = null; } _videoStream = null; _audioStream = null; _audioCodecContext = null; _codecContext = null; if (_swrContext != null) { fixed(SwrContext **s = &_swrContext) { ffmpeg.swr_free(s); } _swrContext = null; } if (pConvertContext != null) { ffmpeg.sws_freeContext(pConvertContext); } if (sampleChannel != null) { sampleChannel.PreVolumeMeter -= SampleChannelPreVolumeMeter; sampleChannel = null; } } catch (Exception ex) { Logger.LogException(ex, "Media Stream (close)"); } finally { try { Program.FfmpegMutex.ReleaseMutex(); } catch { } } PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); }
// sets up libavformat state: creates the AVFormatContext, the frames, etc. to start decoding, but does not actually start the decodingLoop private void prepareDecoding() { const int context_buffer_size = 4096; var fcPtr = ffmpeg.avformat_alloc_context(); formatContext = fcPtr; contextBuffer = (byte *)ffmpeg.av_malloc(context_buffer_size); managedContextBuffer = new byte[context_buffer_size]; readPacketCallback = readPacket; seekCallback = seek; formatContext->pb = ffmpeg.avio_alloc_context(contextBuffer, context_buffer_size, 0, null, readPacketCallback, null, seekCallback); if (ffmpeg.avformat_open_input(&fcPtr, "dummy", null, null) < 0) { throw new Exception("Error opening file."); } if (ffmpeg.avformat_find_stream_info(formatContext, null) < 0) { throw new Exception("Could not find stream info."); } var nStreams = formatContext->nb_streams; for (var i = 0; i < nStreams; ++i) { stream = formatContext->streams[i]; codecParams = *stream->codecpar; if (codecParams.codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO) { timeBaseInSeconds = stream->time_base.GetValue(); var codecPtr = ffmpeg.avcodec_find_decoder(codecParams.codec_id); if (codecPtr == null) { throw new Exception("Could not find codec."); } if (ffmpeg.avcodec_open2(stream->codec, codecPtr, null) < 0) { throw new Exception("Could not open codec."); } frame = ffmpeg.av_frame_alloc(); frameRgb = ffmpeg.av_frame_alloc(); uncompressedFrameSize = ffmpeg.av_image_get_buffer_size(AVPixelFormat.AV_PIX_FMT_RGBA, codecParams.width, codecParams.height, 1); frameRgbBufferPtr = Marshal.AllocHGlobal(uncompressedFrameSize); var dataArr4 = *(byte_ptrArray4 *)&frameRgb->data; var linesizeArr4 = *(int_array4 *)&frameRgb->linesize; var result = ffmpeg.av_image_fill_arrays(ref dataArr4, ref linesizeArr4, (byte *)frameRgbBufferPtr, AVPixelFormat.AV_PIX_FMT_RGBA, codecParams.width, codecParams.height, 1); if (result < 0) { throw new Exception("Could not fill image arrays"); } for (uint j = 0; j < byte_ptrArray4.Size; ++j) { frameRgb->data[j] = dataArr4[j]; frameRgb->linesize[j] = linesizeArr4[j]; } break; } } }
private static unsafe void Main(string[] args) { Console.WriteLine("Runnung in {0}-bit mode.", Environment.Is64BitProcess ? "64" : "32"); // register path to ffmpeg switch (Environment.OSVersion.Platform) { case PlatformID.Win32NT: case PlatformID.Win32S: case PlatformID.Win32Windows: string ffmpegPath = string.Format(@"../../../FFmpeg/bin/windows/{0}", Environment.Is64BitProcess ? "x64" : "x86"); InteropHelper.RegisterLibrariesSearchPath(ffmpegPath); break; case PlatformID.Unix: case PlatformID.MacOSX: string libraryPath = Environment.GetEnvironmentVariable(InteropHelper.LD_LIBRARY_PATH); InteropHelper.RegisterLibrariesSearchPath(libraryPath); break; } // decode 100 frame from url or path //string url = @"../../sample_mpeg4.mp4"; string url = @"http://hubblesource.stsci.edu/sources/video/clips/details/images/centaur_1.mpg"; FFmpegInvoke.av_register_all(); FFmpegInvoke.avcodec_register_all(); FFmpegInvoke.avformat_network_init(); AVFormatContext *pFormatContext = FFmpegInvoke.avformat_alloc_context(); if (FFmpegInvoke.avformat_open_input(&pFormatContext, url, null, null) != 0) { throw new Exception("Could not open file"); } if (FFmpegInvoke.avformat_find_stream_info(pFormatContext, null) != 0) { throw new Exception("Could not find stream info"); } AVStream *pStream = null; for (int i = 0; i < pFormatContext->nb_streams; i++) { if (pFormatContext->streams[i]->codec->codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO) { pStream = pFormatContext->streams[i]; break; } } if (pStream == null) { throw new Exception("Could not found video stream"); } AVCodecContext codecContext = *(pStream->codec); int width = codecContext.width; int height = codecContext.height; AVPixelFormat sourcePixFmt = codecContext.pix_fmt; AVCodecID codecId = codecContext.codec_id; var convertToPixFmt = AVPixelFormat.PIX_FMT_BGR24; SwsContext * pConvertContext = FFmpegInvoke.sws_getContext(width, height, sourcePixFmt, width, height, convertToPixFmt, FFmpegInvoke.SWS_FAST_BILINEAR, null, null, null); if (pConvertContext == null) { throw new Exception("Could not initialize the conversion context"); } var pConvertedFrame = (AVPicture *)FFmpegInvoke.avcodec_alloc_frame(); int convertedFrameBufferSize = FFmpegInvoke.avpicture_get_size(convertToPixFmt, width, height); var pConvertedFrameBuffer = (byte *)FFmpegInvoke.av_malloc((uint)convertedFrameBufferSize); FFmpegInvoke.avpicture_fill(pConvertedFrame, pConvertedFrameBuffer, convertToPixFmt, width, height); AVCodec *pCodec = FFmpegInvoke.avcodec_find_decoder(codecId); if (pCodec == null) { throw new Exception("Unsupported codec"); } // Reusing codec context from stream info, // as an alternative way it could look like this: (but it works not for all kind of codecs) // AVCodecContext* pCodecContext = FFmpegInvoke.avcodec_alloc_context3(pCodec); AVCodecContext *pCodecContext = &codecContext; if ((pCodec->capabilities & FFmpegInvoke.CODEC_CAP_TRUNCATED) == FFmpegInvoke.CODEC_CAP_TRUNCATED) { pCodecContext->flags |= FFmpegInvoke.CODEC_FLAG_TRUNCATED; } if (FFmpegInvoke.avcodec_open2(pCodecContext, pCodec, null) < 0) { throw new Exception("Could not open codec"); } AVFrame *pDecodedFrame = FFmpegInvoke.avcodec_alloc_frame(); var packet = new AVPacket(); AVPacket *pPacket = &packet; FFmpegInvoke.av_init_packet(pPacket); int frameNumber = 0; while (frameNumber < 100) { if (FFmpegInvoke.av_read_frame(pFormatContext, pPacket) < 0) { throw new Exception("Could not read frame"); } if (pPacket->stream_index != pStream->index) { continue; } int gotPicture = 0; int size = FFmpegInvoke.avcodec_decode_video2(pCodecContext, pDecodedFrame, &gotPicture, pPacket); if (size < 0) { throw new Exception(string.Format("Error while decoding frame {0}", frameNumber)); } if (gotPicture == 1) { Console.WriteLine("frame: {0}", frameNumber); byte **src = &pDecodedFrame->data_0; byte **dst = &pConvertedFrame->data_0; FFmpegInvoke.sws_scale(pConvertContext, src, pDecodedFrame->linesize, 0, height, dst, pConvertedFrame->linesize); byte *convertedFrameAddress = pConvertedFrame->data_0; var imageBufferPtr = new IntPtr(convertedFrameAddress); int linesize = pConvertedFrame->linesize[0]; using (var bitmap = new Bitmap(width, height, linesize, PixelFormat.Format24bppRgb, imageBufferPtr)) { bitmap.Save(@"frame.buffer.jpg", ImageFormat.Jpeg); } frameNumber++; System.Threading.Thread.Sleep(1000); } } FFmpegInvoke.av_free(pConvertedFrame); FFmpegInvoke.av_free(pConvertedFrameBuffer); FFmpegInvoke.sws_freeContext(pConvertContext); FFmpegInvoke.av_free(pDecodedFrame); FFmpegInvoke.avcodec_close(pCodecContext); FFmpegInvoke.avformat_close_input(&pFormatContext); }
internal protected InputFormatContext(AVFormatContext *ptr, bool isOwner) : base(ptr, isOwner) { }
/// <inheritdoc /> public unsafe void OnVideoFrameDecoded(AVFrame *videoFrame, AVFormatContext *context) => Parent?.RaiseVideoFrameDecodedEvent(videoFrame, context);
private void DoStart() { var vss = Source; if (!IsAudio) { vss = Tokenise(vss); } if (string.IsNullOrEmpty(vss)) { ErrorHandler?.Invoke("Source not found"); _res = ReasonToFinishPlaying.VideoSourceError; CleanUp(); _starting = false; return; } AVDictionary *options = null; if (_inputFormat == null) { var prefix = vss.ToLower().Substring(0, vss.IndexOf(":", StringComparison.Ordinal)); ffmpeg.av_dict_set_int(&options, "rw_timeout", _timeoutMicroSeconds, 0); ffmpeg.av_dict_set_int(&options, "tcp_nodelay", 1, 0); switch (prefix) { case "https": case "http": case "mmsh": case "mms": ffmpeg.av_dict_set_int(&options, "timeout", _timeoutMicroSeconds, 0); ffmpeg.av_dict_set_int(&options, "stimeout", _timeoutMicroSeconds, 0); if (!string.IsNullOrEmpty(_cookies)) { ffmpeg.av_dict_set(&options, "cookies", _cookies, 0); } if (!string.IsNullOrEmpty(_headers)) { ffmpeg.av_dict_set(&options, "headers", _headers, 0); } if (!string.IsNullOrEmpty(_userAgent)) { ffmpeg.av_dict_set(&options, "user_agent", _userAgent, 0); } break; case "rtsp": case "rtmp": ffmpeg.av_dict_set_int(&options, "stimeout", _timeoutMicroSeconds, 0); if (!string.IsNullOrEmpty(_userAgent)) { ffmpeg.av_dict_set(&options, "user_agent", _userAgent, 0); } if (!string.IsNullOrEmpty(_modeRTSP)) { ffmpeg.av_dict_set(&options, "rtsp_transport", _modeRTSP, 0); } ffmpeg.av_dict_set(&options, "rtsp_flags", "prefer_tcp", 0); break; default: ffmpeg.av_dict_set_int(&options, "timeout", _timeoutMicroSeconds, 0); break; case "tcp": ffmpeg.av_dict_set_int(&options, "timeout", _timeoutMicroSeconds, 0); break; case "udp": ffmpeg.av_dict_set_int(&options, "timeout", _timeoutMicroSeconds, 0); break; } ffmpeg.av_dict_set_int(&options, "buffer_size", BUFSIZE, 0); } //ffmpeg.av_dict_set_int(&options, "rtbufsize", BUFSIZE, 0); var lo = _options.Split(Environment.NewLine.ToCharArray()); foreach (var nv in lo) { if (!string.IsNullOrEmpty(nv)) { var i = nv.IndexOf('='); if (i > -1) { var n = nv.Substring(0, i).Trim(); var v = nv.Substring(i + 1).Trim(); if (!string.IsNullOrEmpty(n) && !string.IsNullOrEmpty(v)) { int j; if (int.TryParse(v, out j)) { ffmpeg.av_dict_set_int(&options, n, j, 0); } else { ffmpeg.av_dict_set(&options, n, v, 0); } } } } } _abort = false; try { Program.MutexHelper.Wait(); var pFormatContext = ffmpeg.avformat_alloc_context(); _lastPacket = DateTime.UtcNow; _interruptCallback = InterruptCb; _interruptCallbackAddress = Marshal.GetFunctionPointerForDelegate(_interruptCallback); _aviocb = new AVIOInterruptCB_callback_func { Pointer = _interruptCallbackAddress }; pFormatContext->interrupt_callback.callback = _aviocb; pFormatContext->interrupt_callback.opaque = null; pFormatContext->max_analyze_duration = 0; //0 = auto var t = _timeoutMicroSeconds; _timeoutMicroSeconds = Math.Max(_timeoutMicroSeconds, 15000000); Throw("OPEN_INPUT", ffmpeg.avformat_open_input(&pFormatContext, vss, _inputFormat, &options)); _formatContext = pFormatContext; SetupFormat(); _timeoutMicroSeconds = t; } catch (Exception ex) { ErrorHandler?.Invoke(ex.Message); _res = ReasonToFinishPlaying.VideoSourceError; CleanUp(); } finally { try { Program.MutexHelper.Release(); } catch { } } _starting = false; }
/// <inheritdoc /> public unsafe void OnSubtitleDecoded(AVSubtitle *subtitle, AVFormatContext *context) => Parent?.RaiseSubtitleDecodedEvent(subtitle, context);
private void CleanUp() { try { Program.MutexHelper.Wait(); if (pConvertedFrameBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(pConvertedFrameBuffer); pConvertedFrameBuffer = IntPtr.Zero; } if (_formatContext != null) { if (_formatContext->streams != null) { var j = (int)_formatContext->nb_streams; for (var i = j - 1; i >= 0; i--) { var stream = _formatContext->streams[i]; if (stream != null && stream->codec != null && stream->codec->codec != null) { stream->discard = AVDiscard.AVDISCARD_ALL; ffmpeg.avcodec_close(stream->codec); } } } fixed(AVFormatContext **f = &_formatContext) { ffmpeg.avformat_close_input(f); } _formatContext = null; } if (_hwDeviceCtx != null) { var f = _hwDeviceCtx; ffmpeg.av_buffer_unref(&f); _hwDeviceCtx = null; } _videoStream = null; _audioStream = null; _audioCodecContext = null; _videoCodecContext = null; if (_swrContext != null) { fixed(SwrContext **s = &_swrContext) { ffmpeg.swr_free(s); } _swrContext = null; } if (pConvertContext != null) { ffmpeg.sws_freeContext(pConvertContext); pConvertContext = null; } if (sampleChannel != null) { sampleChannel.PreVolumeMeter -= SampleChannelPreVolumeMeter; sampleChannel = null; } } catch (Exception ex) { Logger.LogException(ex, SourceName + ": Media Stream (close)"); } finally { try { Program.MutexHelper.Release(); } catch { } } PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); }