h264 sei信息 解码_H264解码之读取本地H264文件

读取本地文件,并逐帧读取:

onReadThread():

void RtspVideo::onReadThread()

{

// 解码参数

char *virInBuf = new char[MAX_DECODER_INPUT_BUFFER_SIZE];

//初始化文件读入buf

if (init_frame_parser() < 0) {

fprintf(stderr, "Error: init frame parser\n");

}

// find the first SPS,PPS,SEI header -> 读取h264文件头到frmbuf中

int frmlen;

uint8_t * frmbuf;

if ((frmlen = read_one_frame(fpi, &frmbuf, 1)) <= 0) {

fprintf(stderr, "Error: cannot find header\n");

deinit_frame_parser();

}

do {

// read one frame

if ((frmlen = read_one_frame(fpi, &frmbuf, 0)) <= 0) {

break;

}

memcpy(virInBuf, frmbuf + 4, frmlen-4);

{

Poco::Mutex::ScopedLock s(m_bufLock);

MyStruct *stu = new MyStruct();

stu->pData = new char[frmlen-4];

memcpy(stu->pData, virInBuf, frmlen-4);

stu->nLen = frmlen-4;

m_pDataCtrl.push_back(stu);

//OutputDebugStringA("=========================\n");

}

} while (1);

delete[] virInBuf;

}

int read_one_frame(FILE *fp, uint8_t **buf, int header):

int RtspVideo::read_one_frame(FILE *fp, uint8_t **buf, int header)

{

int ustart, uend;

int cstart, cend;

int found;

uint8_t nal_unit_type;

// 从文件中读取一段数据到fbuf缓冲区中,读取的长度是缓冲区最大长度的一半

// fstart==fend : empty

// we keep fstart<=fend. whenever fend goes beyond fbufsz, we move the data back to [0 ...)

int rsz;

if (!end_of_file && fend - fstart < fbufsz / 2) { // fbuf is less than half full

if (fstart > fbufsz / 2) { // move back to [0 ...)

memcpy(fbuf, fbuf + fstart, fend - fstart);

fend -= fstart;

fstart = 0;

}

// fill up to half: fbufsz/2-fend+fstart

rsz = fread(fbuf + fend, 1, fbufsz / 2 - fend + fstart, fp);

if (rsz < (int)(fbufsz / 2 - fend + fstart)) { // end of file

printf("We have read all data from the input file\n");

end_of_file = 1;

}

if (rsz > 0)

fend += rsz;

}

if (fend > fbufsz) {

fprintf(stderr, "Opps: this should never happen!\n");

return -1;

}

// 读取文件头数据

// now either fbuf is half full or it is end of file

if (header) { // find header

// find the first SPS,PPS,SEI header

found = 0;

cstart = cend = -1;

while (find_nal_unit(fbuf + fstart, fend - fstart, &ustart, &uend) > 0) {

nal_unit_type = fbuf[fstart + ustart] & 0x1f;

if (nal_unit_type == (uint8_t)6 || nal_unit_type == (uint8_t)7 || nal_unit_type == (uint8_t)8) {

// SEI, SPS or PPS

if (!found) {

found = 1;

cstart = fstart + ustart-4; // the start of first SPS, PPS or SEI, fbuf[cstart]: 00 00 01

// if (cstart > 0 && !fbuf[cstart - 1])

// cstart--;

}

}

else {

if (found) {

cend = fstart + ustart-4; // the end of header before the following picture slice NAL. fbuf[cend]: 00 00 01

// if (!fbuf[cend - 1]) { // the following picture slice has a long start code 00 00 00 01

// cend--;

// }

break;

}

}

fstart += uend; // now fbuf[fstart] is the first byte of start code of next NAL

}

if (cstart < 0 || cend < 0) {

fprintf(stderr, "Error: cannot find a NAL header.\n");

buf = NULL;

if (!end_of_file)

fprintf(stderr, "You should consider increase fbufsz. Current fbufsz=%d.\n", fbufsz);

return -1;

}

fstart = cend;

// now fbuf[cstart,cend) should contain the first SPS,PPS,SEI header

printf("Header: cstart=%x, cend=%x, length=%d\n", cstart, cend, cend - cstart);

*buf = fbuf + cstart;

return cend - cstart;

}

// 读取一段NALU数据

cstart = cend = -1;

found = 0;

while (find_nal_unit(fbuf + fstart, fend - fstart, &ustart, &uend) > 0) {

nal_unit_type = fbuf[fstart + ustart] & 0x1f;

if (nal_unit_type == (uint8_t)6 || nal_unit_type == (uint8_t)7 || nal_unit_type == (uint8_t)8) {

// SEI, SPS or PPS

if (!found) {

found = 1;

cstart = fstart + ustart - 4 ; // the start of first SPS, PPS or SEI, fbuf[cstart]: 00 00 01

// if (cstart > 0 && !fbuf[cstart - 1])

// cstart--;

cend = fstart + uend;

break;

}

}

else if (nal_unit_type == (uint8_t)1 || nal_unit_type == (uint8_t)5) { // IDR or non-IDR

if (!found) { // no header

cstart = fstart + ustart - 4;

// if (cstart > 0 && !fbuf[cstart - 1])

// cstart--;

}

cend = fstart + uend;

break;

}

cstart = fstart + ustart - 4;

fstart += uend; // now fbuf[fstart] is the first byte of start code of next NAL

}

if (cstart < 0 || cend < 0) {

//printf("No more NALs. Exiting\n");

buf = NULL;

if (!end_of_file)

fprintf(stderr, "You should consider increase fbufsz. Current fbufsz=%d.\n", fbufsz);

return -1;

}

fstart = cend;

*buf = fbuf + cstart;

return cend - cstart+2;

}

int find_nal_unit(uint8_t* buf, int size, int* nal_start, int* nal_end):

/** this function is taken from the h264bitstream library written by Alex Izvorski and Alex Giladi

Find the beginning and end of a NAL (Network Abstraction Layer) unit in a byte buffer containing H264 bitstream data.

@param[in] buf the buffer

@param[in] size the size of the buffer

@param[out] nal_start the beginning offset of the nal

@param[out] nal_end the end offset of the nal

@return the length of the nal, or 0 if did not find start of nal, or -1 if did not find end of nal

*/

int RtspVideo::find_nal_unit(uint8_t* buf, int size, int* nal_start, int* nal_end)

{

if (NULL == buf)

{

return 0;

}

int i;

// find start

*nal_start = 0;

*nal_end = 0;

i = 0;

while ( //( next_bits( 24 ) != 0x000001 && next_bits( 32 ) != 0x00000001 )

//(buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0x01) &&

(buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0 || buf[i + 3] != 0x01)

)

{

i++; // skip leading zero

if (i + 4 >= size) { return 0; } // did not find nal start

}

// if (buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0x01) // ( next_bits( 24 ) != 0x000001 )

// {

// i++;

// }

if (buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0 || buf[i + 3] != 0x01) // ( next_bits( 24 ) != 0x000001 )

{

i++;

}

//if (buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0x01) { /* error, should never happen */ return 0; }

//i += 3;

if (buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0 || buf[i + 3] != 0x01) { /* error, should never happen */ return 0; }

i += 4;

*nal_start = i;

// while ( //( next_bits( 24 ) != 0x000000 && next_bits( 24 ) != 0x000001 )

// (buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0) &&

// (buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0x01)

// )

// {

// i++;

// // FIXME the next line fails when reading a nal that ends exactly at the end of the data

// if (i + 3 >= size) { *nal_end = size; return -1; } // did not find nal end, stream ended first

// }

while ( //( next_bits( 24 ) != 0x000000 && next_bits( 24 ) != 0x000001 )

//(buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0) &&

(buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0 || buf[i + 3] != 0x01)

)

{

i++;

// FIXME the next line fails when reading a nal that ends exactly at the end of the data

if (i + 4 >= size) { *nal_end = size; return -1; } // did not find nal end, stream ended first

}

*nal_end = i;

return (*nal_end - *nal_start);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值