【H.264】H.264详解(二)—— H264视频码流解析示例源码

文章目录

    • 一、前言
    • 二、示例源码
      • 【1】目录结构
      • 【2】Makefile源码
      • 【3】h264parser.c源码
      • 【4】编译运行
      • 【5】源码下载地址

声明:此篇示例源码非原创,原作者雷霄骅。雷霄骅,中国传媒大学通信与信息系统专业博士生,在此向雷霄骅雷神致敬。
代码原文地址:视音频数据处理入门:H.264视频码流解析

一、前言

示例源码是一个H.264码流解析程序。该程序可以从H.264码流中分析得到它的基本单元NALU,分离出NALU,然后再分析NALU的各个字段。

关于NALU的相关内容可参考文章【H.264】H.264详解(一)—— 一文看懂H.264协议

二、示例源码

【1】目录结构

project/
├── Makefile
├── h264parser.c
├── sintel.h264

【2】Makefile源码

app:h264parser.cgcc -o app h264parser.c
clean:rm -f app

【3】h264parser.c源码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef enum {NALU_TYPE_SLICE    = 1,NALU_TYPE_DPA      = 2,NALU_TYPE_DPB      = 3,NALU_TYPE_DPC      = 4,NALU_TYPE_IDR      = 5,NALU_TYPE_SEI      = 6,NALU_TYPE_SPS      = 7,NALU_TYPE_PPS      = 8,NALU_TYPE_AUD      = 9,NALU_TYPE_EOSEQ    = 10,NALU_TYPE_EOSTREAM = 11,NALU_TYPE_FILL     = 12,
} NaluType;typedef enum {NALU_PRIORITY_DISPOSABLE = 0,NALU_PRIRITY_LOW         = 1,NALU_PRIORITY_HIGH       = 2,NALU_PRIORITY_HIGHEST    = 3
} NaluPriority;typedef struct{int startcodeprefix_len;      //! 4 for parameter sets and first slice in picture, 3 for everything else (suggested)unsigned len;                 //! Length of the NAL unit (Excluding the start code, which does not belong to the NALU)unsigned max_size;            //! Nal Unit Buffer sizeint forbidden_bit;            //! should be always FALSEint nal_reference_idc;        //! NALU_PRIORITY_xxxxint nal_unit_type;            //! NALU_TYPE_xxxx    char *buf;                    //! contains the first byte followed by the EBSP
} NALU_t;FILE *h264bitstream = NULL;                //!< the bit stream fileint info2=0, info3=0;static int FindStartCode2 (unsigned char *Buf){if(Buf[0]!=0 || Buf[1]!=0 || Buf[2] !=1) return 0; //0x000001?else return 1;
}static int FindStartCode3 (unsigned char *Buf){if(Buf[0]!=0 || Buf[1]!=0 || Buf[2] !=0 || Buf[3] !=1) return 0;//0x00000001?else return 1;
}int GetAnnexbNALU (NALU_t *nalu){int pos = 0;int StartCodeFound, rewind;unsigned char *Buf;if ((Buf = (unsigned char*)calloc (nalu->max_size , sizeof(char))) == NULL) printf ("GetAnnexbNALU: Could not allocate Buf memory\n");nalu->startcodeprefix_len=3;if (3 != fread (Buf, 1, 3, h264bitstream)){free(Buf);return 0;}info2 = FindStartCode2 (Buf);if(info2 != 1) {if(1 != fread(Buf+3, 1, 1, h264bitstream)){free(Buf);return 0;}info3 = FindStartCode3 (Buf);if (info3 != 1){ free(Buf);return -1;}else {pos = 4;nalu->startcodeprefix_len = 4;}}else{nalu->startcodeprefix_len = 3;pos = 3;}StartCodeFound = 0;info2 = 0;info3 = 0;while (!StartCodeFound){if (feof (h264bitstream)){nalu->len = (pos-1)-nalu->startcodeprefix_len;memcpy (nalu->buf, &Buf[nalu->startcodeprefix_len], nalu->len);     nalu->forbidden_bit = nalu->buf[0] & 0x80; //1 bitnalu->nal_reference_idc = nalu->buf[0] & 0x60; // 2 bitnalu->nal_unit_type = (nalu->buf[0]) & 0x1f;// 5 bitfree(Buf);return pos-1;}Buf[pos++] = fgetc (h264bitstream);info3 = FindStartCode3(&Buf[pos-4]);if(info3 != 1)info2 = FindStartCode2(&Buf[pos-3]);StartCodeFound = (info2 == 1 || info3 == 1);}// Here, we have found another start code (and read length of startcode bytes more than we should// have.  Hence, go back in the filerewind = (info3 == 1)? -4 : -3;if (0 != fseek (h264bitstream, rewind, SEEK_CUR)){free(Buf);printf("GetAnnexbNALU: Cannot fseek in the bit stream file");}// Here the Start code, the complete NALU, and the next start code is in the Buf.  // The size of Buf is pos, pos+rewind are the number of bytes excluding the next// start code, and (pos+rewind)-startcodeprefix_len is the size of the NALU excluding the start codenalu->len = (pos+rewind)-nalu->startcodeprefix_len;memcpy (nalu->buf, &Buf[nalu->startcodeprefix_len], nalu->len);//nalu->forbidden_bit = nalu->buf[0] & 0x80; //1 bitnalu->nal_reference_idc = nalu->buf[0] & 0x60; // 2 bitnalu->nal_unit_type = (nalu->buf[0]) & 0x1f;// 5 bitfree(Buf);return (pos+rewind);
}/*** Analysis H.264 Bitstream* @param url    Location of input H.264 bitstream file.*/
int simplest_h264_parser(char *url){NALU_t *n = NULL;int buffersize=100000;//FILE *myout=fopen("output_log.txt","wb+");FILE *myout=stdout;h264bitstream=fopen(url, "rb+");if (h264bitstream==NULL){printf("Open file error\n");return 0;}n = (NALU_t*)calloc (1, sizeof(NALU_t));if (n == NULL){printf("Alloc NALU Error\n");return 0;}n->max_size=buffersize;n->buf = (char*)calloc (buffersize, sizeof(char));if (n->buf == NULL){free (n);printf ("AllocNALU: n->buf");return 0;}int data_offset=0;int nal_num=0;printf("-----+-------- NALU Table ------+---------+\n");printf(" NUM |   POS   |   IDC  |  TYPE |   LEN   |\n");printf("-----+---------+--------+-------+---------+\n");while(!feof(h264bitstream)){int data_lenth;data_lenth=GetAnnexbNALU(n);char type_str[20]={0};switch(n->nal_unit_type){case NALU_TYPE_SLICE:sprintf(type_str,"SLICE");break;case NALU_TYPE_DPA:sprintf(type_str,"DPA");break;case NALU_TYPE_DPB:sprintf(type_str,"DPB");break;case NALU_TYPE_DPC:sprintf(type_str,"DPC");break;case NALU_TYPE_IDR:sprintf(type_str,"IDR");break;case NALU_TYPE_SEI:sprintf(type_str,"SEI");break;case NALU_TYPE_SPS:sprintf(type_str,"SPS");break;case NALU_TYPE_PPS:sprintf(type_str,"PPS");break;case NALU_TYPE_AUD:sprintf(type_str,"AUD");break;case NALU_TYPE_EOSEQ:sprintf(type_str,"EOSEQ");break;case NALU_TYPE_EOSTREAM:sprintf(type_str,"EOSTREAM");break;case NALU_TYPE_FILL:sprintf(type_str,"FILL");break;}char idc_str[20]={0};switch(n->nal_reference_idc>>5){case NALU_PRIORITY_DISPOSABLE:sprintf(idc_str,"DISPOS");break;case NALU_PRIRITY_LOW:sprintf(idc_str,"LOW");break;case NALU_PRIORITY_HIGH:sprintf(idc_str,"HIGH");break;case NALU_PRIORITY_HIGHEST:sprintf(idc_str,"HIGHEST");break;}fprintf(myout,"%5d| %8d| %7s| %6s| %8d|\n",nal_num,data_offset,idc_str,type_str,n->len);data_offset=data_offset+data_lenth;nal_num++;}//Freeif (n){if (n->buf){free(n->buf);n->buf=NULL;}free (n);}return 0;
}int main(int argc, char* argv[]){simplest_h264_parser("sintel.h264");return 0;
}

【4】编译运行

在这里插入图片描述

【5】源码下载地址

H.264详解(二)- H264视频码流解析示例源码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/876013.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenHarmony 开发

本心、输入输出、结果 文章目录 OpenHarmony 开发前言JonathanOpenHarmony 并不是 AndroidOpenHarmony 应用迁移OpenHarmony 的开发流程OpenHarmony 开发 编辑 | 简简单单 Online zuozuo 地址 | https://blog.csdn.net/qq_15071263 如果觉得本文对你有帮助,欢迎点赞、收藏、评…

2023IMO预选题几何第6题

锐角 △ A B C \triangle ABC △ABC 的外接圆为 ω \omega ω, 圆 I I I 与 ω \omega ω 内切于 A A A, 且与 B C BC BC 切于点 D D D. 设直线 A B AB AB, A C AC AC 分别与 I I I 交于点 P P P, Q Q Q, 点 M M M, N N N 在直线 B C BC BC 上, 满足 B B B 是 …

CeoMax总裁主题最新3.8.1破解免授权版/WordPress付费资源素材下载主题

CeoMax总裁主题最新3.8.1破解免授权版&#xff0c;一套WordPress付费资源素材下载的主题&#xff0c;感觉这是做资源站唯一一个可以和ripro媲美甚至超越的模板&#xff0c;UI很美&#xff0c;功能也很强大&#xff0c;有想学习的可下载搭建学习一下&#xff0c;仅供学习研究借鉴…

仿学校网页

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,initial-scale1.0"><title>学校网页</title> <style>.WebTop{backg…

誉天网络安全课程怎么样

学员服务质量保障讲师团队&#xff1a;平均5年课程交付经验&#xff0c;授课质量有保障辅导团队&#xff1a;实验论述辅导讲师&#xff0c;实验备考环境复刻&#xff0c;备考资料完善&#xff0c;及时更新就业服务&#xff1a;简历制作培训&#xff0c;面试技巧培训&#xff0c…

昇思MindSpore学习入门-轻量化数据处理

在资源条件允许的情况下&#xff0c;为了追求更高的性能&#xff0c;一般使用Pipeline模式执行数据变换Transforms。 基于Pipeline模式执行的最大特点是需要使用map方法&#xff0c;如下图中将Resize、Crop、HWC2CHW交由map调度&#xff0c;由其负责启动和执行给定的Transform…

R语言统计分析——控制流

参考资料&#xff1a;R语言实战【第2版】 语句&#xff08;statement&#xff09;是一条单独的R语言或一组复合语言&#xff08;包含在花括号{}中的一组R语言&#xff0c;使用分号分隔&#xff09; 条件&#xff08;cond&#xff09;是一条最终被解析为真&#xff08;TRUE&…

python黑马笔记

运算符&#xff1a; 算术运算符&#xff1a; 加 - 减 * 乘 / 除 // 整除 % 取余 ** 求平方 除法计算得出的结果都是小数 赋值运算符&#xff1a; 标准赋值&#xff1a; 复合赋值&#xff1a; 、 - 、 * 、 / 、// 、 ** 字符串&#xff1a; 字符串拓展内容&#xf…

护网紧急情况应对指南:Linux 应急响应手册

继上一篇&#xff1a;护网紧急情况应对指南&#xff1a;Windows版v1.2全新升级版 之后 收到小伙伴后台要Linux应急手册&#xff0c;今天给大家安排上。 《Linux应急手册》是一本为Linux系统管理员和运维工程师量身打造的实用指南&#xff0c;旨在帮助他们快速应对各种突发状况…

基于FFMPEG和SDL的音视频解码播放的实现过程与相关细节

目录 1、视频播放器原理 2、FFMPEG解码 2.1 FFMPEG库 2.2、数据类型 2.3、解码 2.3.1、接口函数 2.3.2、解码流程 3、SDL播放 3.1、接口函数 3.2、视频播放 3.3、音频播放 4、音视频的同步 4.1、获取音频的播放时间戳 4.2、获取当前视频帧时间戳 4.3、获取视…

MATLAB仿真:数字信号处理用FFT对信号分析

目录 1.实验目的 2 实验原理 3.实验仪器及设备 4.实验步骤及内容 (1)对以下序列进行谱分析。 (2)对以下周期序列进行谱分析。 (3)对模拟周期信号进行谱分析 1.实验目的 学习用 FFT 对连续信号和时域离散信号进行谱分析的方法,了解可能出现的分析误差及其原因,…

CAS算法

CAS算法 1. CAS简介 CAS叫做CompareAndSwap&#xff0c;比较并交换&#xff0c;主要是通过处理器的指令来保证操作的原子性。 CAS基本概念 内存位置 (V)&#xff1a;需要进行CAS操作的内存地址。预期原值 (A)&#xff1a;期望该内存位置上的旧值。新值 (B)&#xff1a;如果旧…

The Llama 3 Herd of Models.Llama 3 模型论文全文

现代人工智能(AI)系统是由基础模型驱动的。本文提出了一套新的基础模型,称为Llama 3。它是一组语言模型,支持多语言、编码、推理和工具使用。我们最大的模型是一个密集的Transformer,具有405B个参数和多达128K个tokens的上下文窗口。本文对Llama 3进行了广泛的实证评价。我们…

DNS 污染/毒化——华为ensp

实验原理:1&#xff0c;用户正常访问 Web页面&#xff0c;会查询本地DNS服务器&#xff0c;一般情况下&#xff0c;本地DNS服务器会设置为 网关地址。2&#xff0c; 攻击者在 用户和网关之间&#xff0c;开启ARP攻击即可&#xff0c;这样&#xff0c;就可以让 用户访问本地DNS服…

【Ant Design Pro】快速上手

初始化 初始化脚手架&#xff1a;快速开始 官方默认使用 umi4&#xff0c;这里文档还没有及时更新&#xff08;不能像文档一样选择 umi 的版本&#xff09;&#xff0c;之后我选择 simple。 然后安装依赖。 在 package.json 中&#xff1a; "start": "cross-e…

卷积的意义及其派生(一)

1.卷积的意义 1.1从LTI的角度看 卷积最开始其实是信号处理中用来描述线性移不变系统Linear time-invariant systems的。线性&#xff0c;表明可以叠加&#xff0c;信号可以拆分成脉冲的响应&#xff1b;时不变&#xff0c;指信号不随着时间的迁移改变&#xff0c;意味着能量守…

【iOS】——通知机制及底层原理

通知传值概要 通知传值可以跨越多个界面进行传值&#xff0c;一般用于后一个界面向前一个界面传值。 通知传值支持多个接收者&#xff0c;多个对象可以同时接收同一个通知并进行处理。这样可以实现一对多的通信&#xff0c;方便跨多个对象进行值传递。 使用步骤 1.在发送者中…

Latent Factor Analysis via Dynamical Systems:LFADS (Nature methods 2018)

Nature Methods&#xff1a;https://www.nature.com/articles/s41592-018-0109-9 LFADS Run Manager for Matlab&#xff1a;https://lfads.github.io/lfads-run-manager/ 目录 Single session:假设&#xff1a;方法&#xff1a;结果&#xff1a; Multi-sessions:假设&#xff…

【C++】位运算:两整数之和

1.题目 2.算法思路 本题不能只用 -&#xff0c;那大概率用到位运算符。 异或的作用是无进位相加&#xff0c;所以需要通过异或运算&#xff08;^&#xff09;来替代加法运算&#xff0c;但是我们无法确定进位的信息。所以需要与运算&#xff08;&&#xff09;来得到进位的…

【Android】Activity生命周期与五种启动模式

文章目录 生命周期返回栈Activity状态生命周期方法 启动模式standard模式singleTask模式singleTop模式singleInstance模式singleInstancePerTask模式配置方式 生命周期 返回栈 每个Activity的状态由它在Activity栈&#xff08;又叫“回退栈back stack”&#xff09;中的位置决…