1. 程式人生 > >如何從H264原始資料SPS裡面得到視訊的長寬

如何從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位)。


相關推薦

如何H264原始資料SPS裡面得到視訊

有這樣一種需求,給你一個h264原始資料檔案,讓你直接播放出來,如何實現? 思路是這樣的,H264原始資料格式都是 0x00000001後面跟0x67 0x68 0x65 0x41這樣的資料,解碼需要一個完整的NAL資料單元,我們需要將每個0x00000001以及下一個0x

vlc接收到資料流到播放視訊的過程分析

    VLC API documentation  或者VLC developer documentation    Chapter 5.  The video output layer  Data structures and main loop  Important data structures ar

嵌入式 vlc接收到資料流到播放視訊的過程分析

Vlc流播放流程  vlc原始碼目錄樹: 目錄名稱 說明 bindings Java, CIL 和Python繫結 doc 幫助文件 (不是更新的) extras 另敘。 include VLC 標頭檔案 libs SRTP庫和

vlc學習計劃(7)--接收到資料流到播放視訊的過程分析

從接收到資料流到播放視訊的過程分析   從網路接收到流->對資料流進行視訊和音訊分離->對視訊用解碼器解碼->顯示解碼後的視訊流<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:off

使用 ffmpeg 進行網路推流:拉流->解封裝->解碼->處理原始資料(音訊、視訊)->編碼->編碼->推流

簡要說明: 1、可拉流:rtmp、rtsp、http 2、可推流: #include "stdafx.h" extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #

資料處理--reshape2包(資料

寬資料 ozone wind temp 1 23.62 11.623 65.55 2 29.44 10.267 79.10 3 59.12 8.942 83.90 4 59.96 8.794 83.97 長資料 variable value 1 ozone 23.

video遠端獲取資料跳轉新頁面開始播放視訊

效果: 獲取電影資料每行3個 video.html <div id="item-video-animation" class="mui-control-content"> <div id="videoAnimation" style="text-align: cen

零開始的鐳射通訊(第1章 協議棧)——4、原始資料編解碼

從零開始的鐳射通訊(第1章 協議棧)——4、原始資料編解碼 github 簡介 移動位置法 提取最高位法 函式說明 github https://github.com/HaHaHaHaHaGe/mynet

【備忘】大資料學習菜鳥到精通學習路線視訊教程

 01.第一階段 大資料必備linux基礎與實戰    02.第二階段 大資料hadoop家族架構實戰    03.第三階段 大資料實時分析Storm入門到精通    04.第四階段 新一代大資料Spark平臺實戰    05.第五階段 知名公司大資料專案實戰

RNN文字分類——原始資料處理到預測類別標籤

這兩天做了一個小專案,是一個文因互聯文字分類的競賽題目,但已經過期了,只是使用它的資料做一下。本次使用的RNN+LSTM模型,最終訓練的正確率為87%,不過每次訓練正確率有些差別,並且還有很多可調引數沒有調整,只是當一個練手的了。由於訓練時間很長,完整的程式碼以

Android 網路請求原理以及原始資料

我們在請求網路的時候都是使用各種框架,或者是 Android SDK 為我們提供的網路請求類。但是你知不知道原始的網路請求包是什麼樣的呢?或許你說這有什麼作用,我會使用框架就好了。很顯然,這種想法是有問題的。一些網路請求的基本知識我們還是需要掌握的。這對我們更深入的開發和掌握更深的技術是非常有必要的。 關於

tensorflow--檔案讀取資料

讀取資料-csv tensorflow讀取資料流程 構造檔案佇列 讀取佇列內容 reader = tf.TextLineReader() 解析成一個樣本資料 example, label = tf.decode_csv(value, record_defaults

mysql安裝,以及csv插入資料

1.mysql安裝     用管理員身份開啟cmd命令列工具,cd到解壓檔案的bin目錄:    ・MySql的Windows服務安裝: mysqld install 回車  ・生成無密碼的root使用者: mysqld --initialize-insecure 

Python 遍歷資料裡面的內容 5*

root_path='./result' sub_path=root_path+'./tmp' for root, dirs, files in os.walk(sub_path): for file in files: if os.path.splitext(file)[

html 裡面鑲嵌視訊,一種是video,一種是iframe

1,解決iframe不能全屏的問題 <iframe style="width:98%;height: 450px;" src='{$vo.url}' frameborder=0 allowfullscreen="true" webkitallowfullscreen="tru

jQueryAjax++servlet+json實現頁面載入時後臺讀取資料

在eclipse中新建一個專案,我起名為Demo 新建一個html檔案,在其中引入外部jQuery和自定義的js檔案 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <sc

java中控制檯輸入資料和輸出資料到控制檯

1.從控制檯輸入資料 1.使用Scanner類來完成從命令列輸入資料到自己的程式中。 2.Scanner類是JDK1.5【jdk5.0】新增的一個開發類庫。 3.Scanner類使用     3.1先匯入Scanner類所在的程式包【java.util.Sca

資料庫查詢資料並輸出到前臺頁面

<?php        //獲取資料庫中的所有留言           require_once("connect.php");   &nbs

java學習實驗隨筆-------如何鍵盤輸入資料並儲存到陣列中

從鍵盤輸入並儲存 public static void main(String[] args) {  Scanner reader = new Scanner(System.in);       /使用Scanner庫進行輸入操作 int[] a = ne

STM32模式接受資料

在實際應用中,會碰到上位機往單片機發送資料的情況,這時候需要配置微控制器為從裝置,準備接受資料 使用硬體I2C時,開啟事件和快取中斷 I2C_ITConfig(SLAVER_I2C, I2C_IT_EVT | I2C_IT_BUF, ENABLE); 然後在中斷服務函式中接受資料