前段时间需要用到在android里面软解码h264视频,就到网上找了些fmmepg的移植代码,可是虽然接口给我了,但是还是不会用。记录下研究新得把,太无聊了。
在h264里面,分为VCL层和NAL层。VCL为实际的h264实现,所有视频文件格式存储,具体的编解码工作都在这一层。
NAL层,我理解的是传输层,不管是在本地播放还是在网络播放的传输,都要通过这一层来传输。h264的文件被分割为
很多个叫着NAL的一个个小块,很多个小的NAL被组成一个完整的帧,也就是一个完整的画面。我要做的就是把这些NAL
包从文件里面分割出来传给fmpeg的解码函数。
package com.h264.codec;
import java.io.FileInputStream;
import java.io.InputStream;
public class H264Decoder {
private int mask = 0x0F0F0F0F;
int getNextNal(byte[] nalBuf, int nalBufUsed, byte[] dataBuf,
int dataBufUsed, int dataRemain) {
int i = 0;
byte data;
for (i = 0; i < dataRemain; i++) {
data = dataBuf[i + dataBufUsed];
nalBuf[i + nalBufUsed] = data;
mask <<= 8;
mask |= data;
if (mask == 1) {
i++;
break;
}
}
return i;
}
public void decode(InputStream is) throws Exception {
boolean firstFlag = true;
int nalLen;
int read = 0;
int nalBufUsed = 0;
int dataBufUsed = 0;
byte[] nalBuf = new byte[40960]; // 40k
byte[] dataBuf = new byte[2048];
while ((read = is.read(dataBuf, 0, 2048)) > 0) {
dataBufUsed = 0;
while (read - dataBufUsed > 0) {
nalLen = getNextNal(nalBuf, nalBufUsed, dataBuf, dataBufUsed,
read - dataBufUsed);
nalBufUsed += nalLen;
dataBufUsed += nalLen;
if (mask == 1) {
mask = 0xFFFFFFFF;
if (firstFlag == true) {// the first start flag
firstFlag = false;
} else {
// decode nal
decoderNal(nalBuf, nalBufUsed-4);
}
nalBuf[0] = 0;
nalBuf[1] = 0;
nalBuf[2] = 0;
nalBuf[3] = 1;
nalBufUsed = 4;
}
}
}
is.close();
}
private void decoderNal(byte[] nalBuf, int length) {
//具体的解码函数,需要调用c接口
}
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream("D:/document/h264decoder/352x288.avi");
H264Decoder test = new H264Decoder();
test.decode(is);
}
}