AVDataProcess/H264Parser.java

239 lines
8.5 KiB
Java
Raw Normal View History

2018-01-25 02:46:38 +00:00
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>
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>
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;
}
}