flv 解封装
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define DEBUG_INFO
- typedef struct FileHeader {
- unsigned char type[4]; // UI8 * 3 "FLV"
- unsigned char versions; // UI8 版本号
- unsigned char stream_info;//UI8 流信息
- unsigned int length; // UI32 文件长度
- }_FileHeader;
- typedef struct TagHeader {
- unsigned char type; // UI8 tag类型
- unsigned int data_size; // UI24 数据区长度
- unsigned int timestemp; // UI24 时间戳
- unsigned char time_stamp_extended; //UI8 扩展时间戳
- unsigned int stream_id; //UI24 流id
- }_TagHeader;
- typedef struct Tag {
- _TagHeader *header;
- unsigned char *data;
- }_Tag;
- _Tag *malloc_tag()
- {
- _Tag *tag = malloc(sizeof(_Tag));
- if (tag == NULL) {
- fprintf(stderr, "malloc tag error\n");
- perror("malloc error:");
- return NULL;
- }
- tag->header = NULL;
- tag->data = NULL;
- return tag;
- }
- void free_tag(_Tag **tag)
- {
- if(tag != NULL){
- if(*tag == NULL){
- return;
- }
- if ((*tag)->header != NULL) {
- free((*tag)->header);
- (*tag)->header = NULL;
- }
- if ((*tag)->data != NULL) {
- free((*tag)->data);
- (*tag)->data = NULL;
- }
- *tag = NULL;
- }
- }
- int reverse_32(unsigned int a)
- {
- union {
- int i;
- char c[4];
- } u, r;
- u.i = a;
- r.c[0] = u.c[3];
- r.c[1] = u.c[2];
- r.c[2] = u.c[1];
- r.c[3] = u.c[0];
- return r.i;
- }
- int reverse_24(unsigned int a)
- {
- union {
- int i;
- char c[4];
- } u, r;
- u.i = a;
- r.c[0] = u.c[2];
- r.c[1] = u.c[1];
- r.c[2] = u.c[0];
- r.c[3] = 0;
- return r.i;
- }
- int read_file_header(FILE *pf, _FileHeader **p_header)
- {
- int ret = 0;
- _FileHeader *header = malloc(sizeof(_FileHeader));
- if (header == NULL) {
- fprintf(stderr, "malloc file header error\n");
- perror("malloc error:");
- return -1;
- }
- memset(header, 0, sizeof(_FileHeader));
- //read file type
- if ((ret = fread(header->type, 3, 1, pf)) <= 0) {
- goto __err_exit;
- }
- // read version, Usually 1
- if ((ret = fread(&(header->versions), 1, 1, pf)) <= 0) {
- goto __err_exit;
- }
- // read stream info
- if ((ret = fread(&(header->stream_info), 1, 1, pf)) <= 0) {
- goto __err_exit;
- }
- // read file length
- if((ret = fread(&(header->length), 4, 1, pf)) <= 0){
- goto __err_exit;
- }
- header->length = reverse_32(header->length);
- *p_header = header;
- #ifdef DEBUG_INFO
- printf("=========== file header=============\n");
- printf("type : %s\n", header->type);
- printf("versions : %u\n", header->versions);
- printf("stream_info : %u\n", header->stream_info);
- printf("length : %d\n", header->length);
- printf("====================================\n");
- #endif
- return 1;
- __err_exit:
- free(header);
- fprintf(stderr, "read file header error\n");
- perror("fread error:");
- return ret;
- }
- int check_file_header(_FileHeader *header)
- {
- // is flv file?
- if ((header->type[0] != 0x46/*'F'*/) || (header->type[1] != 0x4C/*'L'*/) || (header->type[2] != 0x56/*'V'*/)) {
- fprintf(stderr, "check file header type error\n");
- return -1;
- }
- //UB[7]~UB[3]总为0,
- //UB[1]总为0
- //UB[2]=1 Audio
- if (header->stream_info & 0x04) {
- printf("have audio tag\n");
- }
- //UB[0] = 1 Video
- if (header->stream_info & 0x01) {
- printf("have video tag\n");
- }
- return 1;
- }
- int read_last_tag_size(FILE *pf, unsigned int *p_last_tag_size)
- {
- int ret = 0;
- unsigned int last_tag_size = 0;
- if ((ret = fread(&last_tag_size, 4, 1, pf)) <= 0) {
- fprintf(stderr, "read last tag size error\n");
- perror("fread error:");
- return ret;
- }
- *p_last_tag_size = reverse_32(last_tag_size);
- #ifdef DEBUG_INFO
- printf("---last tag size %x\n", *p_last_tag_size);
- #endif
- return 1;
- }
- int read_tag_header(FILE *pf, _TagHeader **p_header)
- {
- int ret = 0;
- _TagHeader *header = NULL;
- header = malloc(sizeof(_TagHeader));
- if (header == NULL) {
- fprintf(stderr, "malloc tag header error\n");
- perror("malloc error:");
- return -1;
- }
- // read tag type , 0x08 is audio, 0x09 is video, 0x12 is script
- if ((ret = fread(&(header->type), 1, 1, pf)) <= 0) {
- goto __err_exit;
- }
- // read tag data size
- if ((ret = fread(&(header->data_size), 3, 1, pf)) <= 0) {
- goto __err_exit;
- }
- header->data_size = reverse_24(header->data_size);
- // read tag timestemp
- if ((ret = fread(&(header->timestemp), 3, 1, pf)) <= 0) {
- goto __err_exit;
- }
- header->timestemp = reverse_24(header->timestemp);
- //read tag extended time stemp
- if ((ret = fread(&(header->time_stamp_extended), 1, 1, pf)) <= 0) {
- goto __err_exit;
- }
- //read stream id
- if ((ret = fread(&(header->stream_id), 3, 1, pf)) <= 0) {
- goto __err_exit;
- }
- header->stream_id = reverse_24(header->stream_id);
- *p_header = header;
- #ifdef DEBUG_INFO
- printf("======= tag header =======\n");
- printf("tag_type:%x\n", header->type);
- printf("data_size:%x\n", header->data_size);
- printf("timestemp:%x\n", header->timestemp);
- printf("time_stamp_extended:%x\n", header->time_stamp_extended);
- printf("stream_id:%x\n", header->stream_id);
- #endif
- return 1;
- __err_exit:
- free(header);
- fprintf(stderr, "read tag header error\n");
- perror("fread error:");
- return ret;
- }
- int read_tag_data(FILE *pf, unsigned char **p_data, unsigned int size)
- {
- int ret = 0;
- unsigned char *data = NULL;
- data = malloc(size + 1);
- if (data == NULL) {
- fprintf(stderr, "malloc tag data error\n");
- perror("malloc error:");
- return -1;
- }
- data[size] = 0;
- if ((ret = fread(data, size, 1, pf)) <= 0) {
- free(data);
- fprintf(stderr, "read tag data error\n");
- perror("fread error:");
- return ret;
- }
- *p_data = data;
- return 1;
- }
- void audio_tag_data(unsigned char *data)
- {
- unsigned char audio_info = 0;
- unsigned char audio_format = 0;
- unsigned char audio_samplerate = 0;
- unsigned char audio_samplelenght = 0;
- unsigned char audio_type = 0;
- // the first byte is the adio info
- audio_info = data[0];
- //UB[7]~UB[4] is the audo format
- // 0 -- 未压缩
- // 1 -- ADPCM
- // 2 -- MP3
- // 5 -- Nellymoser 8kHz momo
- // 6 -- Nellymose
- audio_format = audio_info & 0xf0;
- audio_format >>= 4;
- //UB[3]~UB[2] is the sample rate
- // 0 -- 5.5kHz
- // 1 -- 11kHz
- // 2 -- 22kHz
- // 3 -- 44kHz
- audio_samplerate = audio_info & 0x0c;
- audio_samplerate >>= 2;
- //UB[1] is the sample length
- // 0 -- snd8Bit
- // 1 -- snd16Bit
- audio_samplelenght = audio_info & 0x02;
- audio_samplelenght >>= 1;
- //UB[0] is the type
- // 0 -- sndMomo
- // 1 -- sndStereo
- audio_type = audio_info & 0x01;
- #ifdef DEBUG_INFO
- printf("=======audio_info====\n");
- printf("format:%x\n", audio_format);
- printf("samplerate:%x\n", audio_samplerate);
- printf("samplelenght:%x\n", audio_samplelenght);
- printf("type:%x\n", audio_type);
- #endif
- }
- void video_tag_data(unsigned char *data)
- {
- int size = 0;
- unsigned char video_info = 0;
- unsigned char video_frame_type = 0;
- unsigned char video_code_id = 0;
- // the first byte is the adio info
- video_info = data[0];
- //UB[7]~UB[4] is the video format
- // 1 -- keyframe
- // 2 -- inner frame
- // 3 -- disposable inner frame (H.263 only)
- video_frame_type = video_info & 0xf0;
- video_frame_type >>= 4;
- // UB[3]~UB[0] is the encoder id
- // 2 -- Seronson H.263
- // 3 -- Screen video
- // 4 -- On2 VP6
- // 5 -- On2 VP6 without channel
- // 6 -- Screen video version 2
- video_code_id = video_info & 0x0f;
- #ifdef DEBUG_INFO
- printf("=======video_info====\n");
- printf("frame_type:%x\n", video_frame_type);
- printf("code_id:%x\n", video_code_id);
- #endif
- }
- void script_tag_data(unsigned char *data)
- {
- //Metadata Tag
- /*
- * 该类型Tag又通常被称为Metadata Tag,
- * 会放一些关于FLV视频和音频的参数信息,
- * 如duration、width、height等。
- * 通常该类型Tag会跟在File Header后面作为第一个Tag出现,
- * 而且只有一个。
- * 一般来说,该Tag Data结构包含两个AMF包。
- * 第一个AMF包封装字符串类型数据,
- * 用来装入一个“onMetaData”标志,
- * 这个标志与Adobe的一些API调用有,在此不细述。
- * 第二个AMF包封装一个数组类型,
- * 这个数组中包含了音视频信息项的名称和值。
- */
- // amf 封闭在这里不解了,会在以后文章中见到。
- }
- int read_tag(FILE *pf, unsigned int *p_last_tag_size, _Tag *tag)
- {
- int ret = 0;
- // last tag size
- if ((ret = read_last_tag_size(pf, p_last_tag_size)) <= 0) {
- return ret;
- }
- // read tag header
- if ((ret = read_tag_header(pf, &(tag->header))) <= 0) {
- return ret;
- }
- //read tag data
- if ((ret = read_tag_data(pf, &(tag->data), tag->header->data_size)) <= 0) {
- return ret;
- }
- // 通常第一个音频和视频包都是sequence header
- switch(tag->header->type){
- case 0x8: //audio
- audio_tag_data(tag->data);
- break;
- case 0x9: //video
- video_tag_data(tag->data);
- break;
- case 0x12: //script
- script_tag_data(tag->data);
- break;
- }
- return 1;
- }
- int main()
- {
- FILE *pf = NULL;
- _FileHeader *file_header = NULL;
- unsigned int last_tag_size = 0;
- _Tag *tag = NULL;
- // open file
- if ((pf = fopen("./sample.flv", "rb")) == NULL) {
- perror("fopen error:");
- return -1;
- }
- //read file header add check some info
- if (read_file_header(pf, &file_header) <= 0) {
- fclose(pf);
- fprintf(stderr, "read_file_header error\n");
- return -1;
- }
- // check header info
- if(check_file_header(file_header) <= 0){
- fclose(pf);
- free(file_header);
- fprintf(stderr, "check_file_header error\n");
- return -1;
- }
- for ( ; ; ) {
- free_tag(&tag);
- tag = malloc_tag();
- if(tag == NULL){
- fprintf(stderr, "malloc tag error\n");
- perror("malloc error:");
- break;
- }
- if (read_tag(pf, &last_tag_size, tag) <= 0){
- break;
- }
- }
- free_tag(&tag);
- free(file_header);
- fclose(pf);
- return 0;
- }
flv 解封装的更多相关文章
- FLV视频封装格式详解
FLV视频封装格式详解 分类: FFMpeg编解码 2012-04-04 21:13 1378人阅读 评论(2) 收藏 举报 flvheaderaudiovideocodecfile 目录(?)[-] ...
- FFmpeg音视频解封装
一 . 解封装用到的函数和结构体 1.av_register_all() : open 一次就调用一次 2.avformat_network_init() : 网络模块初始化 3.avformat_o ...
- FFmpeg(二) 解封装相关函数理解
一.解封装基本流程 ①av_register_All()////初始化解封装,注册解析和封装的格式. ②avformat_netword_init()//初始化网络,解析rtsp协议 ③avforma ...
- FFmpeg4.0笔记:封装ffmpeg的解封装功能类CDemux
Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff CDemux.h /*********************** ...
- GRE封装解封装过程
GRE(Generic Routing Encapsulation,通用路由封装)协议是对某些网络层协议(IPX, AppleTalk, IP,etc.)的数据报文进行封装,使这些被封装的数据报文能够 ...
- 【转】FLV视频封装格式详解
Overview Flash Video(简称FLV),是一种流行的网络格式.目前国内外大部分视频分享网站都是采用的这种格式. File Structure 从整个文件上开看,FLV是由The FLV ...
- 详解封装微信小程序组件及小程序坑(附带解决方案)
一.序 上一篇介绍了如何从零开发微信小程序,博客园审核变智障了,每次代码都不算篇幅,好好滴一篇原创,不到3分钟从首页移出来了.这篇介绍一下组件封装和我的踩坑历程. 二.封装微信小程序可复用组件 首先模 ...
- OSI互联数据包封装与解封装过程
当我们在七层协议最上层,主机A想和其它主机通信, 比如telnet到主机B,各层都为数据打包后再封装上自己能识别的数据标签,现在我们只说四层以下的通信过程. .当一个高层的数据包到达传输层,由于tel ...
- 详解封装源码包成RPM包
源码编译安装是最常用安装软件方式,可是面对工作量巨大时候就需要我们的RPM包上场了,统一的模块,一键安装.在面对一定数量的服务器上,RPM就可以为我们节省大量的时间. RPM可以在网上下载,但是当我们 ...
随机推荐
- 快速切题 poj 1002 487-3279 按规则处理 模拟 难度:0
487-3279 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 247781 Accepted: 44015 Descr ...
- Qt出现QObject::connect: Cannot queue arguments of type '******'的解决方法
一般出现这种情况都是自定义的类型进行型号槽连接的时候出现的,使用 假设自定义的类型是MyClass 使用qRegisterMetaType<MyClass>("MyClass&q ...
- 【Sizzle学习】之关于【初探 jQuery 的 Sizzle 选择器】这篇文章里的小bug
[题记]不可否认,这篇文章写得非常好,但是今天我在看sizzle源码的时候,发现这文章有一地方说的不妥.重现:当selectors为"p.class1>p.class2",j ...
- 网络编程的基本概念,TCP/IP协议简介
8.1.1 网络基础知识 计算机网络形式多样,内容繁杂.网络上的计算机要互相通信,必须遵循一定的协议.目前使用最广泛的网络协议是Internet上所使用的TCP/IP协议. 网络编程的目的就是指直接或 ...
- Xen,VMware ESXi,Hyper-V和KVM等虚拟化技术的原理解析
Xen,VMware ESXi,Hyper-V和KVM等虚拟化技术的原理解析 2018年04月03日 13:51:55 阅读数:936 XEN 与 VMware ESXi,Hyper-V 以及 K ...
- windows下类似Linux下的grep命令
今天要查看windws下代理服务器有哪些IP连接过来,但使用 netstat -na 后出现很多连接会话,不方便查看. 想到Linux下的grep非常方便,于是网络上搜寻,还是有类似的命令findst ...
- JAVA多线程------用1
火车上车厢的卫生间,为了简单,这里只模拟一个卫生间,这个卫生间会被多个人同时使用,在实际使用时,当一个人进入卫生间时则会把卫生间锁上,等出来时 打开门,下一个人进去把门锁上,如果有一个人在卫生间内部则 ...
- ubuntu 安装nodejs/npm
安装发行稳定版 Ubuntu 默认仓库里带有Node.js,版本较旧,这并不是最新版,但是应该很稳定.执行如下命令: 1 2 sudo apt-getupdate sudo apt-getinst ...
- BZOJ4518 Sdoi2016 征途 【斜率优化DP】 *
BZOJ4518 Sdoi2016 征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m ...
- jquery 给新增的addClass 使用css样式
假如有一个情况,当导航url找不到相同的地址,就会出现找不到地址,高亮当前导航不出现 解决 办法 记得使用文档载入完成后执行的函数. 因为 .current 是 addClass 新增的class $ ...