239 lines
8.5 KiB
Java
239 lines
8.5 KiB
Java
|
|
|||
|
import java.io.File;
|
|||
|
import java.io.FileInputStream;
|
|||
|
import java.io.InputStream;
|
|||
|
import java.util.ArrayList;
|
|||
|
import java.util.List;
|
|||
|
import java.util.Formatter;
|
|||
|
|
|||
|
public class H264Parser {
|
|||
|
|
|||
|
//0x00000001<30><31>0x000001<30><31>һ<EFBFBD><D2BB>nalu<6C><75><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>˱<EFBFBD>־ʱΪ<CAB1><CEAA>nalu<6C>Ľ<EFBFBD>β<EFBFBD><CEB2>
|
|||
|
//<2F><>ʼ<EFBFBD><CABC>־<EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ֽڣ<D6BD>type<70><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>nalu<6C><75><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>type & 0x1F<31><46>Ϊ<EFBFBD><CEAA>nalu<6C><75><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>nalu_type<70><65><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
private static final int NALU_TYPE_SLICE = 1; //<2F><>IDRͼ<52><CDBC><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB>ֵ<EFBFBD>Ƭ<EFBFBD>Σ<EFBFBD>ΪP<CEAA><50>B֡
|
|||
|
private static final int NALU_TYPE_DPA = 2; //<2F><>IDRͼ<52><CDBC><EFBFBD><EFBFBD>A<EFBFBD><41><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD>Ƭ<EFBFBD><C6AC>
|
|||
|
private static final int NALU_TYPE_DPB = 3; //<2F><>IDRͼ<52><CDBC><EFBFBD><EFBFBD>B<EFBFBD><42><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD>Ƭ<EFBFBD><C6AC>
|
|||
|
private static final int NALU_TYPE_DPC = 4; //<2F><>IDRͼ<52><CDBC><EFBFBD><EFBFBD>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD>Ƭ<EFBFBD><C6AC>
|
|||
|
private static final int NALU_TYPE_IDR = 5; //IDRͼ<52><CDBC><EFBFBD><EFBFBD>Ƭ<EFBFBD>Σ<EFBFBD><CEA3>ؼ<EFBFBD>֡<EFBFBD><D6A1>I֡
|
|||
|
private static final int NALU_TYPE_SEI = 6; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><C7BF>Ϣ
|
|||
|
private static final int NALU_TYPE_SPS = 7; //<2F><><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Sequence Parameter Set<65><74>
|
|||
|
private static final int NALU_TYPE_PPS = 8; //ͼ<><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PPS<50><53>Picture Parameter Set<65><74>
|
|||
|
private static final int NALU_TYPE_AUD = 9; //<2F>ָ<EFBFBD><D6B8><EFBFBD>
|
|||
|
private static final int NALU_TYPE_EOSEQ = 10; //<2F><><EFBFBD>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
private static final int NALU_TYPE_EOSTREAM = 11; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
private static final int NALU_TYPE_FILL = 12; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
private static final int NALU_PRIORITY_DISPOSABLE = 0;
|
|||
|
private static final int NALU_PRIORITY_LOW = 1;
|
|||
|
private static final int NALU_PRIORITY_HIGH = 2;
|
|||
|
private static final int NALU_PRIORITY_HIGHEST = 3;
|
|||
|
|
|||
|
private boolean mFirstFind = true; //<2F><>һ<EFBFBD>β<EFBFBD><CEB2><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
|
|||
|
private int mStartCodeLen = 0; //<2F><>ʼ<EFBFBD>볤<EFBFBD><EBB3A4>
|
|||
|
private int mCurStartCodeLen = 0;
|
|||
|
private int mFrameLen = 0; //֡<><D6A1><EFBFBD><EFBFBD>
|
|||
|
private int mFrameFirstByte = 0; //֡<><D6A1><EFBFBD><EFBFBD><EFBFBD>еĵ<D0B5>һ<EFBFBD><D2BB><EFBFBD>ֽ<EFBFBD>
|
|||
|
private int mCurFrameFirstByte = 0;
|
|||
|
private int mPos = 0;
|
|||
|
private int mLen = 0;
|
|||
|
private String mStartCode = "";
|
|||
|
|
|||
|
private int mNaluType = 0;
|
|||
|
private int mForbiddenBit = 0;
|
|||
|
private int mNalReferenceIdc = 0;
|
|||
|
|
|||
|
public static void main(String[] args) {
|
|||
|
if (args.length > 0) {
|
|||
|
H264Parser h264Parser = new H264Parser();
|
|||
|
h264Parser.ParseH264(args[0]);
|
|||
|
} else {
|
|||
|
System.out.println("Missing h264 filename.");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//<2F><><EFBFBD><EFBFBD>NALU<4C><55>Ӧ<EFBFBD><D3A6>SliceΪһ֡<D2BB>Ŀ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>0x00000001(<28><>4<EFBFBD><34><EFBFBD>ֽڳ<D6BD><DAB3><EFBFBD>)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0x000001(<28><>3<EFBFBD><33><EFBFBD>ֽڳ<D6BD><DAB3><EFBFBD>)<29><>
|
|||
|
public int FindStartCode(InputStream inputStream) {
|
|||
|
|
|||
|
byte[] startCode = new byte[4];
|
|||
|
int len = -1;
|
|||
|
|
|||
|
try {
|
|||
|
len = inputStream.read(startCode);
|
|||
|
} catch (Exception e) {
|
|||
|
e.printStackTrace();
|
|||
|
}
|
|||
|
|
|||
|
if (len == 3) {
|
|||
|
if (startCode[0]==0 && startCode[1]==0 && startCode[2]==1) {
|
|||
|
len = 3;
|
|||
|
} else {
|
|||
|
len = 0;
|
|||
|
}
|
|||
|
} else if (len == 4) {
|
|||
|
if (startCode[0]==0 && startCode[1]==0 && startCode[2]==0 && startCode[3]==1) {
|
|||
|
len = 4;
|
|||
|
} else {
|
|||
|
len = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return len;
|
|||
|
}
|
|||
|
|
|||
|
public int FindStartCode(List<Integer> startCodeList) {
|
|||
|
|
|||
|
int len = startCodeList.size();
|
|||
|
|
|||
|
if (len == 3) {
|
|||
|
if (startCodeList.get(0)==0 && startCodeList.get(1)==0 && startCodeList.get(2)==1) {
|
|||
|
return 3;
|
|||
|
}
|
|||
|
} else if (len == 4) {
|
|||
|
if (startCodeList.get(0)==0 && startCodeList.get(1)==0 && startCodeList.get(2)==0 && startCodeList.get(3)==1) {
|
|||
|
return 4;
|
|||
|
} else if (startCodeList.get(0)==0 && startCodeList.get(1)==0 && startCodeList.get(2)==1) {
|
|||
|
return 3;
|
|||
|
}
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
public int GetNalu(InputStream inputStream) {
|
|||
|
mPos = mPos + mLen;
|
|||
|
|
|||
|
//<2F><>һ<EFBFBD>β<EFBFBD><CEB2><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD>룬ֻ<EBA3AC><D6BB>Ϊ<EFBFBD><CEAA><EFBFBD>ƶ<EFBFBD><C6B6>ļ<EFBFBD>ָ<EFBFBD><D6B8>
|
|||
|
if (mFirstFind) {
|
|||
|
mFirstFind = false;
|
|||
|
if (-1 == (mStartCodeLen = FindStartCode(inputStream))) {
|
|||
|
return -1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (mStartCodeLen == 3) {
|
|||
|
mStartCode = "001";
|
|||
|
} else {
|
|||
|
mStartCode = "0001";
|
|||
|
}
|
|||
|
|
|||
|
List<Integer> startCodeList = new ArrayList<>();
|
|||
|
int frameLen = 0;
|
|||
|
while(true) {
|
|||
|
int tmp = -1;
|
|||
|
|
|||
|
//һ<><D2BB><EFBFBD>ֽ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ֽڴ<D6BD><DAB4>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ж<EFBFBD>ȡ
|
|||
|
try {
|
|||
|
tmp = inputStream.read();
|
|||
|
} catch (Exception e) {
|
|||
|
e.printStackTrace();
|
|||
|
}
|
|||
|
|
|||
|
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD>ļ<EFBFBD>β
|
|||
|
if (tmp == -1) {
|
|||
|
mFrameLen = frameLen;
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
//֡<><D6A1><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD><EFBFBD>ۼ<EFBFBD>
|
|||
|
frameLen++;
|
|||
|
|
|||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>ж<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><DDB1>浽list<73><74>
|
|||
|
startCodeList.add(tmp);
|
|||
|
|
|||
|
//<2F><>һ֡<D2BB>ĵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ֽ<EFBFBD><D6BD>л<EFBFBD>ȡNALU<4C><55>Ϣ
|
|||
|
if (frameLen == 1) {
|
|||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>β<EFBFBD><CEB2>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD>볤<EFBFBD><EBB3A4><EFBFBD><EFBFBD>3<EFBFBD><33><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><CFB4>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ֽڵ<D6BD><DAB5><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if (mStartCodeLen == 3) {
|
|||
|
tmp = mFrameFirstByte;
|
|||
|
frameLen++; //֡<><D6A1><EFBFBD>ȼ<EFBFBD><C8BC>ϵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ֽ<EFBFBD>
|
|||
|
}
|
|||
|
mCurFrameFirstByte = tmp;
|
|||
|
mForbiddenBit = tmp & 0x80;
|
|||
|
mNalReferenceIdc = tmp & 0x60;
|
|||
|
mNaluType = tmp & 0x1f;
|
|||
|
}
|
|||
|
|
|||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8>ֽڵ<D6BD>list<73><74>
|
|||
|
if (startCodeList.size() < 4) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD>룬<EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>0<EFBFBD>ͱ<EFBFBD>ʾ<EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD>
|
|||
|
int startCodeLen = FindStartCode(startCodeList);
|
|||
|
if (startCodeLen > 0) {
|
|||
|
if (startCodeLen == 3) {
|
|||
|
mFrameFirstByte = tmp;
|
|||
|
}
|
|||
|
frameLen = frameLen - 4;
|
|||
|
mLen = frameLen + mStartCodeLen;
|
|||
|
mStartCodeLen = startCodeLen;
|
|||
|
break;
|
|||
|
}
|
|||
|
startCodeList.remove(0);
|
|||
|
}
|
|||
|
mFrameLen = frameLen;
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
public boolean ParseH264(String fileName) {
|
|||
|
if (fileName.equals("")) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
InputStream inputStream = null;
|
|||
|
try {
|
|||
|
File file = new File(fileName);
|
|||
|
inputStream = new FileInputStream(file);
|
|||
|
} catch (Exception e) {
|
|||
|
e.printStackTrace();
|
|||
|
inputStream = null;
|
|||
|
}
|
|||
|
if (inputStream == null) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
System.out.println("-----+---------+----- NALU Table -+---------+------------+");
|
|||
|
System.out.println(" NUM | POS | IDC | TYPE | LEN | START_CODE |");
|
|||
|
System.out.println("-----+---------+---------+--------+---------+------------+");
|
|||
|
|
|||
|
int iNaluNum = 0;
|
|||
|
while(true) {
|
|||
|
int dataLen = GetNalu(inputStream);
|
|||
|
|
|||
|
iNaluNum++;
|
|||
|
String sNaluType = "";
|
|||
|
switch(mNaluType) {
|
|||
|
case NALU_TYPE_SLICE: sNaluType = "SLICE"; break;
|
|||
|
case NALU_TYPE_DPA: sNaluType = "DPA"; break;
|
|||
|
case NALU_TYPE_DPB: sNaluType = "DPB"; break;
|
|||
|
case NALU_TYPE_DPC: sNaluType = "DPC"; break;
|
|||
|
case NALU_TYPE_IDR: sNaluType = "IDR"; break;
|
|||
|
case NALU_TYPE_SEI: sNaluType = "SEI"; break;
|
|||
|
case NALU_TYPE_SPS: sNaluType = "SPS"; break;
|
|||
|
case NALU_TYPE_PPS: sNaluType = "PPS"; break;
|
|||
|
case NALU_TYPE_AUD: sNaluType = "AUD"; break;
|
|||
|
case NALU_TYPE_EOSEQ: sNaluType = "EOSEQ"; break;
|
|||
|
case NALU_TYPE_EOSTREAM: sNaluType = "EOSTREAM"; break;
|
|||
|
case NALU_TYPE_FILL: sNaluType = "FILL"; break;
|
|||
|
}
|
|||
|
String sIdc = "";
|
|||
|
switch(mNalReferenceIdc >> 5) {
|
|||
|
case NALU_PRIORITY_DISPOSABLE:sIdc = "DISPOS"; break;
|
|||
|
case NALU_PRIORITY_LOW: sIdc = "LOW"; break;
|
|||
|
case NALU_PRIORITY_HIGH: sIdc = "HIGH"; break;
|
|||
|
case NALU_PRIORITY_HIGHEST: sIdc = "HIGHEST";break;
|
|||
|
}
|
|||
|
Formatter formatter = new Formatter(System.out);
|
|||
|
formatter.format("%5d| %8d| %8s| %7s| %8d| %11s|\n", iNaluNum, mPos, sIdc, sNaluType, mFrameLen, mStartCode);
|
|||
|
if (dataLen == -1) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
inputStream.close();
|
|||
|
} catch (Exception e) {
|
|||
|
e.printStackTrace();
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|