美文网首页直播Srs
rtmp视频流提取h264裸流

rtmp视频流提取h264裸流

作者: 爱吃花栗鼠的猫 | 来源:发表于2017-11-27 18:35 被阅读434次

流媒体服务器在判断出消息类型为video之后,进行h264参数集和nalu的提取,并加入分隔符,代码如下
文中用读取文件的方式代替rtmp msg里面的payload
rtmp视频消息示例:

image.png

。。。。


image.png
#include <string>
#include <sstream>

FILE *f264 = NULL;

uint16_t ReadU16BE(uint8_t data[2]) {
    uint16_t v = 0;

    uint16_t v1 = uint16_t(data[0]);
    v1 <<= 16;

    uint16_t v2 = uint16_t(data[1]);

    v |= v1;
    v |= v2;

    return v;
}

uint32_t ReadU32BE(uint8_t data[4]) {
    uint32_t v = 0;

    uint32_t v1 = uint32_t(data[0]);
    v1 <<= 24;

    uint32_t v2 = uint32_t(data[1]);
    v2 <<= 16;

    uint32_t v3 = uint32_t(data[2]);
    v3 <<= 8;

    uint32_t v4 = uint32_t(data[3]);

    v |= v1;
    v |= v2;
    v |= v3;
    v |= v4;

    return v;
}

void write_h264nalu_to_disk(char *nalu, int nalu_len) {
    char separator[4] = {0x00, 0x00, 0x00, 0x01};

    fwrite(separator, 1, 4, f264);
    fwrite(nalu, 1, nalu_len, f264);
}

void parse_one_frame(char *payload, int payload_size) {
    char frame_type = payload[0];
    frame_type = (frame_type >> 4) & 0x0F;


    char avc_packet_type = payload[1];
    if (1 == frame_type && 0 == avc_packet_type)// spspps. 17 00
    {
        //sps
        int offset = 0;
        offset += 11;

        int sps_len = payload[offset] * 16 + payload[offset + 1];
        offset += 2;

        write_h264nalu_to_disk(&payload[offset], sps_len);
        offset += sps_len;

        //pps
        offset += 1; //pps num.
        char nalu_len_data[2] = {payload[offset], payload[offset + 1]};
        int pps_len = ReadU16BE((uint8_t *) nalu_len_data);
        offset += 2;

        offset + pps_len;
        write_h264nalu_to_disk(&payload[offset], pps_len);

    } else if (1 == avc_packet_type) // nalu
    {
        int offset = 0;
        offset += 5;

        while (offset < payload_size) {
            char nalu_len_data[4] = {payload[offset], payload[offset + 1], payload[offset + 2], payload[offset + 3]};
            int nalu_len = ReadU32BE((uint8_t *) nalu_len_data);

            offset += 4;

            write_h264nalu_to_disk(&payload[offset], nalu_len);
            offset += nalu_len;
        }
    }
}

int main() {
    std::string path = "/home/yangkai/CLionProjects/jvsrs/trunk/cmake-build-debug/origin/";

    enum {
        READ_EVERY_TIME = 128
    };

    char *payload = new char[1 * 1024 * 1024];
    int payload_size = 0;

    f264 = fopen("end.264", "wb+");

    for (int i = 0; i < 1956; ++i) {
        std::stringstream ss;
        ss << path << "origin-" << i << ".h264";

        FILE *f = fopen(ss.str().c_str(), "rb");
        while (1) {
            int readsize = fread(payload + payload_size, 1, READ_EVERY_TIME, f);
            payload_size += readsize;

            if (readsize != READ_EVERY_TIME) {
                break;
            }
        }
        fclose(f);

        parse_one_frame(payload, payload_size);
        payload_size = 0;

    }

    delete[] payload;
    fclose(f264);

    return 0;
}

相关文章

  • rtmp视频流提取h264裸流

    流媒体服务器在判断出消息类型为video之后,进行h264参数集和nalu的提取,并加入分隔符,代码如下文中用读取...

  • VideoToolBox 解码H.264

    关于VideoToolBox 解码 H264 ,这次我们通过 ffmpeg 提取一个视频流的 的视频流,也就是 h...

  • 从MP4文件中提取H264视频流

    从MP4文件中提取 aac 音轨 从MP4文件中提取H264裸流 ffmpeg -i file.mp4 -an -...

  • ffmpeg音视频转化

    从MP4文件中提取aac音轨 从MP4文件中提取H264裸流 MP3转换为aac格式 使用aac和h264文件生成...

  • Qt音视频开发8-ffmpeg保存裸流

    一、前言 最开始做的ffmpeg保存视频文件,就是直接保存的裸流数据,裸流数据一般是H264格式的数据,这种数据文...

  • ffmpeg常用命令

    用 来表示视频文件的地址。 查看关键帧数据: 查看流信息: 查看分辨率: 查看每一帧的音频数据: 提取视频的h264码流

  • 《Android音视频系列-7》直播推流

    这篇文章将介绍在Android平台使用RTMPDump来进行直播推流。 一、推流核心思想 推流,可以推H264裸流...

  • IOS-FFmpeg解码

    为了简单化,这里只是从H264视频编码格式,解码为yuv420p的原始图片格式。 H264裸流格式: 这里谈谈H2...

  • 音视频:调试手段

    如何调试H264裸流? 将裸流保存成文件,然后用010 editor看结构,用vlc播放如果有00 00 00 0...

  • RTSP H264/HEVC 流 Wasm 播放

    本文将介绍 RTSP H264/HEVC 裸流如何于网页前端播放。涉及 WebSocket 代理发送流数据, Wa...

网友评论

    本文标题:rtmp视频流提取h264裸流

    本文链接:https://www.haomeiwen.com/subject/iygdbxtx.html