ホーム>source

こんにちは、C#でSharpRtspを実装しましたhttps://github.com/ngraziano/SharpRTSP 私はrtspパケットを受信して​​おり、h264形式を持っていますH264Payloadクラスに次のメソッドがあります

private List<byte[]> Process_H264_RTP_Frame(List<byte[]> rtp_payloads)
        {
            Console.WriteLine("RTP Data comprised of " + rtp_payloads.Count + " rtp packets");
            List<byte[]> nal_units = new List<byte[]>(); // Stores the NAL units for a Video Frame. May be more than one NAL unit in a video frame.
            for (int payload_index = 0; payload_index < rtp_payloads.Count; payload_index++)
            {
                // Examine the first rtp_payload and the first byte (the NAL header)
                int nal_header_f_bit = (rtp_payloads[payload_index][0] >> 7) & 0x01;
                int nal_header_nri = (rtp_payloads[payload_index][0] >> 5) & 0x03;
                int nal_header_type = (rtp_payloads[payload_index][0] >> 0) & 0x1F;
                // If the Nal Header Type is in the range 1..23 this is a normal NAL (not fragmented)
                // So write the NAL to the file
                if (nal_header_type >= 1 && nal_header_type <= 23)
                {
                    Console.WriteLine("Normal NAL");
                    norm++;
                    nal_units.Add(rtp_payloads[payload_index]);
                }
                // There are 4 types of Aggregation Packet (split over RTP payloads)
                else if (nal_header_type == 24)
                {
                    Console.WriteLine("Agg STAP-A");
                    stap_a++;
                    // RTP packet contains multiple NALs, each with a 16 bit header
                    //   Read 16 byte size
                    //   Read NAL
                    try
                    {
                        int ptr = 1; // start after the nal_header_type which was '24'
                        // if we have at least 2 more bytes (the 16 bit size) then consume more data
                        while (ptr + 2 < (rtp_payloads[payload_index].Length - 1))
                        {
                            int size = (rtp_payloads[payload_index][ptr] << 8) + (rtp_payloads[payload_index][ptr + 1] << 0);
                            ptr = ptr + 2;
                            byte[] nal = new byte[size];
                            System.Array.Copy(rtp_payloads[payload_index], ptr, nal, 0, size); // copy the NAL
                            nal_units.Add(nal); // Add to list of NALs for this RTP frame. Start Codes like 00 00 00 01 get added later
                            ptr = ptr + size;
                        }
                    }
                    catch
                    {
                        // do nothing
                    }
                }
                else if (nal_header_type == 25)
                {
                    Console.WriteLine("Agg STAP-B not supported");
                    stap_b++;
                }
                else if (nal_header_type == 26)
                {
                    Console.WriteLine("Agg MTAP16 not supported");
                    mtap16++;
                }
                else if (nal_header_type == 27)
                {
                    Console.WriteLine("Agg MTAP24 not supported");
                    mtap24++;
                }
                else if (nal_header_type == 28)
                {
                    Console.WriteLine("Frag FU-A");
                    fu_a++;
                    // Parse Fragmentation Unit Header
                    int fu_header_s = (rtp_payloads[payload_index][1] >> 7) & 0x01;  // start marker
                    int fu_header_e = (rtp_payloads[payload_index][1] >> 6) & 0x01;  // end marker
                    int fu_header_r = (rtp_payloads[payload_index][1] >> 5) & 0x01;  // reserved. should be 0
                    int fu_header_type = (rtp_payloads[payload_index][1] >> 0) & 0x1F; // Original NAL unit header
                    Console.WriteLine("Frag FU-A s=" + fu_header_s + "e=" + fu_header_e);
                    // Check Start and End flags
                    if (fu_header_s == 1 && fu_header_e == 0)
                    {
                        // Start of Fragment.
                        // Initiise the fragmented_nal byte array
                        // Build the NAL header with the original F and NRI flags but use the the Type field from the fu_header_type
                        byte reconstructed_nal_type = (byte)((nal_header_f_bit << 7) + (nal_header_nri << 5) + fu_header_type);
                        // Empty the stream
                        fragmented_nal.SetLength(0);
                        // Add reconstructed_nal_type byte to the memory stream
                        fragmented_nal.WriteByte(reconstructed_nal_type);
                        // copy the rest of the RTP payload to the memory stream
                        fragmented_nal.Write(rtp_payloads[payload_index], 2, rtp_payloads[payload_index].Length - 2);
                    }
                    if (fu_header_s == 0 && fu_header_e == 0)
                    {
                        // Middle part of Fragment
                        // Append this payload to the fragmented_nal
                        // Data starts after the NAL Unit Type byte and the FU Header byte
                        fragmented_nal.Write(rtp_payloads[payload_index], 2, rtp_payloads[payload_index].Length - 2);
                    }
                    if (fu_header_s == 0 && fu_header_e == 1)
                    {
                        // End part of Fragment
                        // Append this payload to the fragmented_nal
                        // Data starts after the NAL Unit Type byte and the FU Header byte
                        fragmented_nal.Write(rtp_payloads[payload_index], 2, rtp_payloads[payload_index].Length - 2);
                        // Add the NAL to the array of NAL units
                        nal_units.Add(fragmented_nal.ToArray());
                    }
                }
                else if (nal_header_type == 29)
                {
                    Console.WriteLine("Frag FU-B not supported");
                    fu_b++;
                }
                else
                {
                    Console.WriteLine("Unknown NAL header " + nal_header_type + " not supported");
                }
            }
            // Output some statistics
            Console.WriteLine("Norm=" + norm + " ST-A=" + stap_a + " ST-B=" + stap_b + " M16=" + mtap16 + " M24=" + mtap24 + " FU-A=" + fu_a + " FU-B=" + fu_b);
            // Output all the NALs that form one RTP Frame (one frame of video)
            return nal_units;
        }

    }

私は読んだことがありますが、読み終えましたが、H264フレームをビットマップに変換する方法が見つかりませんでした。ビットマップは任意のボディがこのデータをビットマップに変換するのに役立つので、保存したいだけですか?

あなたの答え
  • 解決した方法 # 1

    その関数の終わりはH264形式でデータを返します

    
           // Output all the NALs that form one RTP Frame (one frame of video)
            return nal_units;
    
    

    ビットマップを取得するには、H264データをVideo Decompressorに渡す必要があります。デジタルビデオに慣れていない場合は、.ZIPまたは.RARまたは.7Zファイルを検討してください。 圧縮されたデータを使用可能な形式に変換する適切なソフトウェアがなければ、これらのファイルの内容を読み取ることはできません。 同じことがビデオにも当てはまります。 H264は圧縮データ形式です。 H264解凍コーデックを使用して、nal_unitsをビットマップ(またはYUVと呼ばれる別のビデオ形式)に変換する必要があります。

    この解凍にffmpegを使用する人もいます。その他は、H264データをオペレーティングシステムAPI(MacのVideoToolbox、AndroidのMediaCodecまたはWindowsがサポートするものなど)に渡します。

    ただし、これらの追加手順が必要です。

  • 前へ java - JPAクエリ:サブクエリをグループ化条件に結合する
  • 次へ r - 複数の変数に基づいて最も近い最高値または同等のものを見つける