Exemplo n.º 1
0
        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;
            //    }
            //}
        }
Exemplo n.º 2
0
        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);
        }