通过C语言判断H265帧类型和读裸流文件

H265帧类型判断

H264的Nal Unit头是一个字节,265变成两个字节
和H264的&0x1f不同。H265是
int type =(code & 0x7E)>>1;
0-9是P帧,16-21是关键(I)帧,32-40是VPS SPS PPS SUFFIX SEI NUT等

int read_one_frame(FILE* fp, char** outdate) {
    int size = 0;
    int pps = 0;
    char* ptr = calloc(1, 1024);

    static unsigned char ts[5] = { 0 };

    //防止文件数据错误
    if (fread(ptr, 1, 4, fp) < 4) {
        log_i("read start error\n");
        free(ptr);
        return size;
    }

    if ((*ptr == 0x00) && (*(ptr + 1) == 0x00) && (*(ptr + 2) == 0x00) && (*(ptr + 3) == 0x01)) {

        size = 4;
        while (1) {
            int len = fread(ptr + size, 1, 1024 - size % 1024, fp);
            if (len>0) {
                for (int i = 0; i < len;)
                {
                    ts[0] = ts[1];
                    ts[1] = ts[2];
                    ts[2] = ts[3];
                    ts[3] = ts[4];
                    ts[4] = *(ptr + size);
                    size++;
                    i++;
                    if ((ts[0] == 0x00) && (ts[1] == 0x00) && (ts[2] == 0x00) && (ts[3] == 0x01)) {
                        //读取到下一帧的起始码,即表示这帧读完了,后移文件指针
                        int code = (ts[4] & 0x7E) >> 1;
                        if (code>31)
                        {
                            pps = 1;
                            continue;
                        }if (15 < code && code < 22 && pps)
                        {
                            continue;
                        }

                        size -= 5;
                        fseek(fp, -5 - len + i, SEEK_CUR);
                        goto END;
                    }
                }

                if (0 == size % 1024)
                {
                    ptr = realloc(ptr, size + 1024);
                }
            }
            else
            {
                fseek(fp, 0, SEEK_SET);
                break;//读完文件退出循环
            }

        }
END:    //读取到的数据大小
        *outdate = ptr;
    }
    else {

    }

    return size;
}
 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要解析H.265(HEVC)流中的I、P、B和SPS、PPS等,需要使用HEVC解码器。在C语言中,可以使用开源的HEVC解码库来实现。 常见的HEVC解码库包括libde265、OpenHEVC、FFmpeg等。这些库可以用于解码H.265视频流,并提供API来解析I、P、B、SPS、PPS等。 以下是使用FFmpeg库进行H.265解码的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libavutil/pixdesc.h> int main(int argc, char *argv[]) { int ret; AVFormatContext *fmt_ctx = NULL; AVCodecContext *codec_ctx = NULL; AVCodec *codec = NULL; AVPacket pkt; AVFrame *frame = NULL; int video_stream_idx = -1; if (argc < 2) { fprintf(stderr, "Usage: %s <input file>\n", argv[0]); exit(1); } av_register_all(); // 打开输入文件 ret = avformat_open_input(&fmt_ctx, argv[1], NULL, NULL); if (ret < 0) { fprintf(stderr, "Could not open input file '%s'\n", argv[1]); goto end; } // 查找视频流 ret = avformat_find_stream_info(fmt_ctx, NULL); if (ret < 0) { fprintf(stderr, "Could not find stream information\n"); goto end; } for (int i = 0; i < fmt_ctx->nb_streams; i++) { if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { video_stream_idx = i; } } if (video_stream_idx == -1) { fprintf(stderr, "Could not find video stream\n"); goto end; } // 获取解码器并打开 codec = avcodec_find_decoder(fmt_ctx->streams[video_stream_idx]->codecpar->codec_id); if (!codec) { fprintf(stderr, "Failed to find codec\n"); goto end; } codec_ctx = avcodec_alloc_context3(codec); if (!codec_ctx) { fprintf(stderr, "Failed to allocate codec context\n"); goto end; } ret = avcodec_parameters_to_context(codec_ctx, fmt_ctx->streams[video_stream_idx]->codecpar); if (ret < 0) { fprintf(stderr, "Failed to copy codec parameters to context\n"); goto end; } ret = avcodec_open2(codec_ctx, codec, NULL); if (ret < 0) { fprintf(stderr, "Failed to open codec\n"); goto end; } // 解码循环 while (1) { ret = av_read_frame(fmt_ctx, &pkt); if (ret < 0) { break; } // 判断是否是视频流 if (pkt.stream_index == video_stream_idx) { ret = avcodec_send_packet(codec_ctx, &pkt); if (ret < 0) { fprintf(stderr, "Error sending packet to decoder\n"); break; } while (ret >= 0) { frame = av_frame_alloc(); ret = avcodec_receive_frame(codec_ctx, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { fprintf(stderr, "Error receiving frame from decoder\n"); goto end; } // 处理解码后的 if (frame->key_frame) { printf("I frame\n"); // 处理I } else if (frame->pict_type == AV_PICTURE_TYPE_P) { printf("P frame\n"); // 处理P } else if (frame->pict_type == AV_PICTURE_TYPE_B) { printf("B frame\n"); // 处理B } av_frame_free(&frame); } } av_packet_unref(&pkt); } end: if (codec_ctx) { avcodec_free_context(&codec_ctx); } if (fmt_ctx) { avformat_close_input(&fmt_ctx); } return 0; } ``` 在解码循环中,根据解码后的类型判断是否是I、P或B。如果是I,可以进一步解析SPS、PPS等
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值