如何从H264原始数据SPS里面得到视频的长宽

有这样一种需求,给你一个h264原始数据文件,让你直接播放出来,如何实现?

思路是这样的,H264原始数据格式都是 0x00000001后面跟0x67 0x68 0x65 0x41这样的数据,解码需要一个完整的NAL数据单元,我们需要将每个0x00000001以及下一个0x00000001之前的数据读出来,交给解码器解码。

读文件我就不啰嗦了,本文主要讲解如何从SPS获取视频长宽,SPS即0x67开头数据,读到0x00000001 后一个字节是0x67的后面跟的数据就是SPS了。我们看一个封包里面sps的结构:

我们可以看到 最下面的42开始就是0x67后面的SPS数据了,看H264的官方文档可以知道,SPS里面的参数都是按照bit的形式存储的。

我自己写了一个解析SPS的类,代码如下:

import android.util.Log;

/*
 * Author:Vincent Luo
 * Date: 20150615
 * Description:参考H264标准语法实现对SPS参数的解析
 */
public class H264SPSPaser {
	private static final String TAG = "H264SPSPaser";
	private static int startBit = 0;
	/*
	 * 从数据流data中第StartBit位开始读,读bitCnt位,以无符号整形返回
	 */
	public static short u(byte[] data,int bitCnt,int StartBit){
		short ret = 0;
		int start = StartBit;
		for(int i = 0;i < bitCnt;i++){
			ret<<=1;
			if ((data[start / 8] & (0x80 >> (start%8))) != 0)
			{
				ret += 1;
			}
			start++;
		}
		return ret;
	}
	/*
	 * 无符号指数哥伦布编码
	 * leadingZeroBits = ?1;
	 * for( b = 0; !b; leadingZeroBits++ )
	 *    b = read_bits( 1 )
	 * 变量codeNum 按照如下方式赋值:
	 * codeNum = 2^leadingZeroBits ? 1 + read_bits( leadingZeroBits )
	 * 这里read_bits( leadingZeroBits )的返回值使用高位在先的二进制无符号整数表示。
	 */
	public static short ue(byte[] data,int StartBit){
		short ret = 0;
		int leadingZeroBits = -1;
		int tempStartBit = (StartBit == -1)?startBit:StartBit;//如果传入-1,那么就用上次记录的静态变量
		 for( int b = 0; b != 1; leadingZeroBits++ ){//读到第一个不为0的数,计算前面0的个数
			 b = u(data,1,tempStartBit++);
		 }
		 Log.d(TAG,"ue leadingZeroBits = " + leadingZeroBits + ",Math.pow(2, leadingZeroBits) = " + Math.pow(2, leadingZeroBits) + ",tempStartBit = " + tempStartBit);
		 ret = (short) (Math.pow(2, leadingZeroBits) - 1 + u(data,leadingZeroBits,tempStartBit));
		 startBit = tempStartBit + leadingZeroBits;
		 Log.d(TAG,"ue startBit = " + startBit);
		return ret;
	}
	/*
	 * 有符号指数哥伦布编码
	 * 9.1.1 有符号指数哥伦布编码的映射过程
	 *按照9.1节规定,本过程的输入是codeNum。
	 *本过程的输出是se(v)的值。
	 *表9-3中给出了分配给codeNum的语法元素值的规则,语法元素值按照绝对值的升序排列,负值按照其绝对
	 *值参与排列,但列在绝对值相等的正值之后。
	 *表 9-3-有符号指数哥伦布编码语法元素se(v)值与codeNum的对应
	 *codeNum 语法元素值
	 *	0 		0
	 *	1		1
	 *	2		?1
	 *	3		2
	 *	4		?2
	 *	5		3
	 *	6		?3
	 *	k		(?1)^(k+1) Ceil( k÷2 )
	 */
	public static int se(byte[] data,int StartBit){
		int ret = 0;
		short codeNum = ue(data,StartBit);
		ret = (int) (Math.pow(-1, codeNum + 1)*Math.ceil(codeNum/2));
		return ret;
	}
}

只需调用如下接口即可得到宽高:

int width = (H264SPSPaser.ue(sps,34) + 1)*16;
int height = (H264SPSPaser.ue(sps,-1) + 1)*16;

其中参数sps就是42开始的那一串字节流,34指的是宽开始的位置(bit位)。

时间: 2024-11-06 07:44:58

如何从H264原始数据SPS里面得到视频的长宽的相关文章

[转]【流媒體】H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流

[流媒體]H264—MP4格式及在MP4文件中提取H264的SPS.PPS及码流 SkySeraph Apr 1st 2012  Email:[email protected].com 一.MP4格式基本概念 MP4格式对应标准MPEG-4标准(ISO/IEC14496) 二.MP4封装格式核心概念 1  MP4封装格式对应标准为 ISO/IEC 14496-12(信息技术 视听对象编码的第12部分: ISO 基本媒体文件格式/Information technology Coding of a

(1)h264 ,mpeg4 ,aac 等音视频格式及其基础详解

以下一系列文章均来于网络,其目录如下: h264 ,mpeg4 ,aac 等音视频格式及其基础详解 codec类型 mpeg系列——mpeg1和Mmpeg2 mpeg系列——mpeg4 mpeg系列——aac音频 H26x系列 容器(上) 容器(下) 一 基本概念 1 编解码 编解码器(codec)指的是一个能够对一个信号或者一个数据流进行变换的设备或者程序.这里指的变换既包括将信号或者数据流进行编码(通常是为了传输.存储或者加密)或者提取得到一个编码流的操作,也包括为了观察或者处理从这个编码流

统计指定目录下的视频时长

有时间可以写成递归的 1 package org.zln.video.demo1; 2 3 import it.sauronsoftware.jave.Encoder; 4 import it.sauronsoftware.jave.EncoderException; 5 import it.sauronsoftware.jave.InputFormatException; 6 import it.sauronsoftware.jave.MultimediaInfo; 7 8 import ja

vue / js使用video获取视频时长

项目中遇到上传视频功能,需要有预览和获取视频时长功能,因之前使用upload(有需要的话可以参考下我之前的文章),这里就不赘述,直接用来上传视频,不过在上传之前和上传成功后的钩子里,获取不到时长: 没有时长怎么办呢,只能用原生JS来获取: 上传成功以后,将成功的路径绑定给video 使用js获取duration并赋给时间参数 这时你会发现,你得到的值是NaN 视频还未加载下来,无法同步获取到,使用定时器即可解决 OK了,现在可以获取到了 希望本文对你有所帮助! 原文地址:https://www.

获取音、视频时长(NAudio,Shell32,FFmpeg)

参考网址:https://blog.csdn.net/u013810234/article/details/57471780 以下为本次测试用到的音.视频格式: audio :".wav;.mp3;.wma;.ra;.mid;.ogg;.ape;.au;.aac;"; vedio :".mp4;.mpg;.mpeg;.avi;.rm;.rmvb;.wmv;.3gp;.flv;.mkv;.swf;.asf;"; Note: 1. 测试音.视频均为对应格式的有效文件(下

javascript 获得以秒计的视频时长

<!DOCTYPE html> <html> <body> <h3>演示如何访问 VIDEO 元素</h3> <video id="myVideo" width="320" height="240" controls> <source src="/i/movie.mp4" type="video/mp4"> <sour

layui上传视频并获得视频时长的方法

layui官方上传视频时并没直接提供获取视频时长的方法,需要我们间接获得 HTML增加一个<video>标签,因为video标签可以帮我们获取视频时长 <video id="videoattr" width="250" height="100" ></video> 当然,你也可以设置隐藏. 然后JS就可以利用<video>的duration来得到时长. //同时绑定多个元素,并将属性设定在元素上 u

H.264从SPS中提取视频宽高

H.264有两种封装模式: (1)annexb模式:传统模式,使用start code来分隔NAL, SPS和PPS是在ES流的头部: (2)mp4模式:没有start code,使用NALU长度(固定字节,通常为4个字节)来分隔NAL.AVCodecContext的extradata内部保存着分隔的字节数,SPS和PPS: 1. 找到SPS 视频的宽高保存在SPS中.那么提取宽高首先要找到SPS.annexb模式直接读取视频数据,根据NAL type找到SPS即可.mp4模式应该从extrad

H264参数SPS(序列参数集)和PPS(图像参数集)说明

在文章开始之前,先看图一: 图一 从图一中我们看到SPS,PPS.这是符合H.264码流中第一个NALU是SPS,第二个NALU是PPS.SPS和PPS包含了 初始化H.264解码器所需要的信息参数. SPS包含的是针对一连续编码视频序列的参数,如标识符seq_parameter_set_id.帧数及POC的约束.参考帧数目.解码图像尺寸和帧场编码模式选择标识等. PPS对应的是一个序列中某一副图像或者某几幅图像,参数如标识符pic_parameter_set_id.可选的seq_paramet