Beispiel #1
0
        // H.264 動画で TimeScale が4倍精度になってるか調べる
        public bool IsTimeScaleFour()
        {
            int c;
            int count = 0;

            long[] dts = new long[4];

            if (video_codec_context.codec_id != 28) // H.264 でないので関係ない
            {
                return(false);
            }

            while ((c = AVCodecAPI.av_read_frame(p_avformat_context, p_packet)) >= 0)
            {
                PacketContainer container = new PacketContainer(p_packet);
                if (container.packet.stream_index == video_stream_index)
                {
                    dts[count] = container.packet.dts;
                    ++count;
                }
                container.Destruct();
                if (count >= dts.Length)
                {
                    break;
                }
            }
            AVCodecAPI.av_seek_frame(p_avformat_context, video_stream_index, 0, 0);

            return(dts[1] - dts[0] == 1001 && dts[2] - dts[1] == 1001 && dts[3] - dts[2] == 2002);
        }
Beispiel #2
0
        private PacketContainer ReadPacket()
        {
            if (audio_priority_times_ > 0)
            {
                --audio_priority_times_;

                int c;
                while ((c = AVCodecAPI.av_read_frame(p_avformat_context, p_packet)) >= 0)
                {
                    PacketContainer packet = new PacketContainer(p_packet);

                    if (packet.packet.stream_index == audio_stream_index)
                    {
                        return(packet);
                    }
                    else
                    {
                        av_packet_queue_.Enqueue(packet);
                    }
                }
                if (av_packet_queue_.Count > 0)
                {
                    return(av_packet_queue_.Dequeue());
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                if (av_packet_queue_.Count > 0)
                {
                    return(av_packet_queue_.Dequeue());
                }
                else
                {
                    int c = AVCodecAPI.av_read_frame(p_avformat_context, p_packet);
                    if (c >= 0)
                    {
                        PacketContainer packet = new PacketContainer(p_packet);
                        return(packet);
                    }
                    else
                    {
                        return(null);
                    }
                }
            }
        }
Beispiel #3
0
        public void FixIllegalFrameRate()
        {
            int c;
            int count = 0;

            long[] dts = new long[50];

            while ((c = AVCodecAPI.av_read_frame(p_avformat_context, p_packet)) >= 0)
            {
                PacketContainer container = new PacketContainer(p_packet);
                if (container.packet.stream_index == video_stream_index)
                {
                    dts[count] = container.packet.dts;
                    ++count;
                }
                container.Destruct();
                if (count >= dts.Length)
                {
                    break;
                }
            }
            double average_dts = 0.0;

            for (int i = 5; i < count - 1; ++i) // 最初の5フレームは捨てる
            {
                average_dts += dts[i + 1] - dts[i];
            }
            average_dts /= (double)(count - 1 - 5);

            if (average_dts > 0)
            {
                double new_frame_rate_d = (double)video_stream.time_base.den / video_stream.time_base.num / average_dts;
                int    new_frame_rate   = (int)(new_frame_rate_d * 1000);
                int    new_frame_scale  = 1000;

                new_frame_rate  = 30;
                new_frame_scale = 1;

                for (int i = 0; i < key_frame_list_.Count; ++i)
                {
                    key_frame_list_[i] = (int)((double)key_frame_list_[i] * new_frame_rate * video_scale_
                                               / ((double)new_frame_scale * video_rate_));
                }
                video_rate_  = new_frame_rate;
                video_scale_ = new_frame_scale;
            }

            AVCodecAPI.av_seek_frame(p_avformat_context, video_stream_index, 0, 0);
        }
Beispiel #4
0
        /// <summary>
        /// 動画ファイルを開く
        /// </summary>
        /// <param name="filename">ファイルパス</param>
        /// <param name="width">動画サイズを固定する場合の幅(負の値を指定した場合は元の動画サイズになる)</param>
        /// <param name="height">動画サイズを固定する場合の高さ(負の値を指定した場合は元の動画サイズになる)</param>
        /// <param name="memory_size">使用するメモリサイズ(MB)(負の値を指定した場合は自動設定)</param>
        public void Open(string filename, int video_width, int video_height, int memory_size)
        {
            OpenCodec(filename);

            fixed_video_width_  = video_width;
            fixed_video_height_ = video_height;

            video_rate_  = video_stream.r_frame_rate.num;
            video_scale_ = video_stream.r_frame_rate.den;

            p_frame     = AVCodecAPI.avcodec_alloc_frame();
            p_frame_rgb = AVCodecAPI.avcodec_alloc_frame();

            p_packet = AVCodecAPI.av_malloc(Marshal.SizeOf(new AVPacket()));

            long last_dts = 0;
            int  c        = 0;

            bool is_first    = true;
            int  start_frame = 0;

            while (c >= 0)
            {
                if (!is_first)
                {
                    AVCodecAPI.av_seek_frame(p_avformat_context, video_stream_index, last_dts + 1, 0);
                }

                while ((c = AVCodecAPI.av_read_frame(p_avformat_context, p_packet)) >= 0)
                {
                    PacketContainer container = new PacketContainer(p_packet);
                    if (container.packet.stream_index == video_stream_index)
                    {
                        last_dts = container.packet.dts;
                        key_dts_list_.Add(last_dts);
                        key_frame_list_.Add(DtsToVideoFrame(last_dts));
                        if (is_first)
                        {
                            is_first    = false;
                            start_frame = key_frame_list_[key_frame_list_.Count - 1];
                        }
                        break;
                    }
                    container.Destruct();
                }
            }
            AVCodecAPI.av_seek_frame(p_avformat_context, video_stream_index, 0, 0);

            if (IsTimeScaleFour())
            {
                video_scale_ *= 4;
                for (int i = 0; i < key_frame_list_.Count; ++i)
                {
                    key_frame_list_[i] /= 4;
                }
            }

            if (video_rate_ / video_scale_ > 60)
            {
                FixIllegalFrameRate();
            }

            if (HasVideo)
            {
                if (memory_size <= 0)
                {
                    memory_size = Math.Min(Math.Max(BufferContainer.GetMemorySize() / (1024 * 1024) - 500, 100), 500); // 最小100MB、最大500MB
                }
                video_buffer_manager_ = new VideoBufferManager(this, FrameLength, memory_size * 1024 * 1024 / VideoPictureBufferSize, start_frame);
            }
            if (HasAudio)
            {
                audio_buffer_manager_ = new AudioBufferManager();
                audio_buffer_manager_.SetDataLength(AudioSampleRate * AudioChannel
                                                    * AudioBytesPerSample * format_context.duration / 1000000);

                p_audio_buffer = Marshal.AllocHGlobal(audio_temp_buffer_size_);

                audio_priority_times_ = 10;
            }
            StartDecoding();
        }