예제 #1
0
        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
        }