コード例 #1
0
ファイル: AVCodecManager.cs プロジェクト: tdenc/nicorank
            public BufferContainer GetEmptyBufferContainer(int frame)
            {
                if (current_using_frame_num_ < buffering_frame_limit_)
                {
                    BufferContainer buffer = null;
                    try
                    {
                        buffer = new BufferContainer(parent_.VideoPictureBufferSize);
                    }
                    catch (OutOfMemoryException)
                    {
                        buffering_frame_limit_ = current_using_frame_num_; // ここで打ち止め
                    }
                    if (buffer != null)
                    {
                        ++current_using_frame_num_;
                        return(buffer);
                    }
                }

                if (empty_buffer_stack_.Count > 0)
                {
                    return(empty_buffer_stack_.Pop());
                }
                else
                {
                    int             empty_index = GetEmptyIndex(frame);
                    BufferContainer buffer      = video_buffer_list_[empty_index];
                    video_buffer_list_[empty_index] = null;
                    return(buffer);
                }
            }
コード例 #2
0
ファイル: AVCodecManager.cs プロジェクト: tdenc/nicorank
        private void DecodeVideo(AVPacket packet)
        {
            int frame_finished;

            AVCodecAPI.avcodec_decode_video(video_stream.codec, p_frame, out frame_finished, packet.data, packet.size);

            if (frame_finished > 0)
            {
                BufferContainer buffer    = video_buffer_manager_.GetEmptyBufferContainer(current_frame_);
                double          dummy_val = 0;

                AVCodecAPI.avpicture_fill(p_frame_rgb, buffer.Buffer, (int)AVCodecAPI.AVPixelFormat.PIX_FMT_BGR24,
                                          Width, Height);

                IntPtr sws_context = AVCodecAPI.sws_getContext(video_codec_context.width, video_codec_context.height,
                                                               video_codec_context.pix_fmt, Width, Height,
                                                               (int)AVCodecAPI.AVPixelFormat.PIX_FMT_BGR24, 4, IntPtr.Zero, IntPtr.Zero, ref dummy_val);
                try
                {
                    AVCodecAPI.sws_scale(sws_context, p_frame, new IntPtr(p_frame.ToInt32() + 16), 0,
                                         video_codec_context.height, p_frame_rgb, new IntPtr(p_frame_rgb.ToInt32() + 16));
                }
                finally
                {
                    AVCodecAPI.sws_freeContext(sws_context);
                }
                buffer.Time    = (int)packet.dts;
                current_frame_ = DtsToVideoFrame((int)packet.dts);
                buffer.Frame   = current_frame_;
                video_buffer_manager_.SetBufferContainer(buffer);
            }
        }
コード例 #3
0
ファイル: AVCodecManager.cs プロジェクト: tdenc/nicorank
 public void SetBufferContainer(BufferContainer buffer)
 {
     if (buffer.Frame < 0 || buffer.Frame >= parent_.FrameLength)
     {
         empty_buffer_stack_.Push(buffer);
     }
     else if (video_buffer_list_[buffer.Frame] != null)
     {
         empty_buffer_stack_.Push(buffer);
     }
     else
     {
         video_buffer_list_[buffer.Frame] = buffer;
     }
 }
コード例 #4
0
ファイル: AVCodecManager.cs プロジェクト: tdenc/nicorank
        /// <summary>
        /// フレームを取得する。デコードがまだされていない場合は null が返ると同時に
        /// デコードスレッドに指定したフレーム番号をデコードするように要求する
        /// </summary>
        /// <param name="frame">フレーム番号</param>
        /// <returns></returns>
        public BufferContainer GetFrame(int frame)
        {
            if (frame < 0)
            {
                frame = 0;
            }
            else if (frame >= FrameLength)
            {
                frame = FrameLength - 1;
            }
            BufferContainer buffer = video_buffer_manager_.GetFrame(frame);

            if (buffer == null)
            {
                RequireSeeking(frame);
            }
            return(buffer);
        }
コード例 #5
0
ファイル: AVCodecManager.cs プロジェクト: tdenc/nicorank
        /// <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();
        }