public static void Fill(Demuxer demuxer) { DemuxerInfo di = new DemuxerInfo(); di.Name = Utils.BytePtrToStringUTF8(demuxer.fmtCtx->iformat->name); di.LongName = Utils.BytePtrToStringUTF8(demuxer.fmtCtx->iformat->long_name); di.Extensions = Utils.BytePtrToStringUTF8(demuxer.fmtCtx->iformat->extensions); di.StartTime = demuxer.fmtCtx->start_time * 10; di.Duration = demuxer.fmtCtx->duration * 10; demuxer.info = di; StreamInfo.Fill(demuxer); //for (int i=0; i<demuxer.fmtCtx->nb_streams; i++) //{ // switch (demuxer.fmtCtx->streams[i]->codecpar->codec_type) // { // case AVMEDIA_TYPE_AUDIO: // demuxer.AudioStreams.Add(new EmbeddedAudioStream(demuxer.fmtCtx->streams[i])); // if (demuxer.fmtCtx->streams[i]->duration <= 0) demuxer.AudioStreams[demuxer.AudioStreams.Count-1].Duration = demuxer.decCtx.demuxer.info.Duration; // break; // case AVMEDIA_TYPE_VIDEO: // demuxer.VideoStreams.Add(new EmbeddedVideoStream(demuxer.fmtCtx->streams[i])); // if (demuxer.fmtCtx->streams[i]->duration <= 0) demuxer.VideoStreams[demuxer.VideoStreams.Count-1].Duration = demuxer.decCtx.demuxer.info.Duration; // break; // case AVMEDIA_TYPE_SUBTITLE: // demuxer.SubtitleStreams.Add(new EmbeddedSubtitleStream(demuxer.fmtCtx->streams[i])); // if (demuxer.fmtCtx->streams[i]->duration <= 0) demuxer.SubtitleStreams[demuxer.SubtitleStreams.Count-1].Duration = demuxer.decCtx.demuxer.info.Duration; // break; // } //} }
public int Open(string url, bool doAudio = true, bool doSubs = true, Stream stream = null, bool closeExternals = true) { if (url == null && stream == null) { return(-1); } if (type == MediaType.Video && closeExternals) { decCtx.aDemuxer.Close(); decCtx.sDemuxer.Close(); } Close(closeExternals); int ret; this.url = url; Log($"Opening {url}"); AVDictionary *opt = null; Dictionary <string, string> optPtr = decCtx.cfg.demuxer.GetFormatOptPtr(type); foreach (var t1 in optPtr) { av_dict_set(&opt, t1.Key, t1.Value, 0); } fmtCtx = avformat_alloc_context(); fmtCtx->interrupt_callback.callback = interruptClbk; fmtCtx->interrupt_callback.opaque = (void *)decCtx.decCtxPtr; fmtCtx->flags |= AVFMT_FLAG_DISCARD_CORRUPT; if (stream != null) { if (ioBuffer == null) { ioBuffer = new byte[ioBufferSize]; // NOTE: if we use small buffer ffmpeg might request more than we suggest } ioCtx = avio_alloc_context((byte *)av_malloc(ioBufferSize), ioBufferSize, 0, (void *)decCtx.decCtxPtr, ioread, null, ioseek); fmtCtx->pb = ioCtx; fmtCtx->flags |= AVFMT_FLAG_CUSTOM_IO; ioStream = stream; ioStream.Seek(0, SeekOrigin.Begin); } AVFormatContext *fmtCtxPtr = fmtCtx; ret = avformat_open_input(&fmtCtxPtr, stream != null ? null : url, null, &opt); if (ret < 0) { Log($"[Format] [ERROR-1] {Utils.FFmpeg.ErrorCodeToMsg(ret)} ({ret})"); return(ret); } // validate that we need this av_format_inject_global_side_data(fmtCtx); ret = avformat_find_stream_info(fmtCtx, null); if (ret < 0) { Log($"[Format] [ERROR-2] {Utils.FFmpeg.ErrorCodeToMsg(ret)} ({ret})"); avformat_close_input(&fmtCtxPtr); return(ret); } DemuxerInfo.Fill(this); Log("\r\n[# Format] " + DemuxerInfo.GetDumpAll(this)); // In case of multiple video streams select best Height based on current Display (fallback to default) | Maybe FPS too? ret = -1; if (type == MediaType.Video) { var iresults = from vstream in streams where vstream.Type == AVMEDIA_TYPE_VIDEO && vstream.Height <= decCtx.renderer.Info.ScreenBounds.Height orderby vstream.Height descending select vstream; var results = iresults.ToList(); if (results.Count != 0) { ret = iresults.ToList()[0].StreamIndex; } } if (ret == -1) { ret = av_find_best_stream(fmtCtx, mType, -1, -1, null, 0); } if (ret < 0) { Log($"[Format] [ERROR-3] {Utils.FFmpeg.ErrorCodeToMsg(ret)} ({ret})"); avformat_close_input(&fmtCtxPtr); return(ret); } ret = decoder.Open(this, fmtCtx->streams[ret]); if (ret < 0) { avformat_close_input(&fmtCtxPtr); return(ret); } switch (mType) { case AVMEDIA_TYPE_VIDEO: ret = av_find_best_stream(fmtCtx, AVMEDIA_TYPE_AUDIO, -1, decoder.st->index, null, 0); if (ret >= 0) { defaultAudioStream = ret; } if (doAudio) { if (ret >= 0) { decCtx.aDecoder.Open(this, fmtCtx->streams[ret]); } else if (ret != AVERROR_STREAM_NOT_FOUND) { Log($"[Format] [ERROR-7] [Audio] {Utils.FFmpeg.ErrorCodeToMsg(ret)} ({ret})"); } } if (doSubs) { if ((ret = av_find_best_stream(fmtCtx, AVMEDIA_TYPE_SUBTITLE, -1, decoder.st->index, null, 0)) >= 0) { decCtx.sDecoder.Open(this, fmtCtx->streams[ret]); } else if (ret != AVERROR_STREAM_NOT_FOUND) { Log($"[Format] [ERROR-7] [Subs ] {Utils.FFmpeg.ErrorCodeToMsg(ret)} ({ret})"); } } break; case AVMEDIA_TYPE_AUDIO: break; case AVMEDIA_TYPE_SUBTITLE: break; } RefreshStreams(); if (demuxThread == null || !demuxThread.IsAlive) { demuxThread = new Thread(() => Demux()); demuxThread.Name = $"{type} Demuxer"; demuxThread.IsBackground = true; demuxThread.Start(); while (status != Status.Paused) { Thread.Sleep(5); // Wait for thread to come up } } else { status = Status.Paused; } pkt = av_packet_alloc(); //Console.WriteLine($"CP: {decoder.codecCtx->colorspace} | PR: {decoder.codecCtx->color_primaries} | TRC: {decoder.codecCtx->color_trc} | CR: {decoder.codecCtx->color_range}"); return(0); }