cpp
复制代码
#include <iostream>
#include <fstream>
using namespace std;
extern "C" { //指定函数是c语言函数,函数名不包含重载标注
//引用ffmpeg头文件
#include <libavcodec/avcodec.h>
}
//预处理指令导入库
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
int main(int argc, char* argv[])
{
//1 分割h264 存入AVPacket
// ffmpeg -i v1080.mp4 -s 400x300 test.h264
string filename = "test.h264";
ifstream ifs(filename, ios::binary);
if (!ifs)return -1;
unsigned char inbuf[4096] = { 0 };
AVCodecID codec_id = AV_CODEC_ID_H264;
//1 找解码器
auto codec = avcodec_find_decoder(codec_id);
//2 创建上下文
auto c = avcodec_alloc_context3(codec);
//3 打开上下文
avcodec_open2(c, NULL, NULL);
//分割上下文
auto parser = av_parser_init(codec_id);
auto pkt = av_packet_alloc();
while (!ifs.eof())
{
ifs.read((char*)inbuf, sizeof(inbuf));//将h264编码的流读入inbuf中
int data_size = ifs.gcount();// 读取的字节数
if (data_size <= 0)break;
auto data = inbuf;
while (data_size > 0) //一次有多帧数据
{
/* int av_parser_parse2(AVCodecParserContext * s,
AVCodecContext * avctx,
uint8_t * *poutbuf,
int* poutbuf_size,
const uint8_t * buf,
int buf_size,
int64_t pts,
int64_t dts,
int64_t pos);
s :指向 AVCodecParserContext 的指针,用于维护解析器的状态。
avctx : 指向 AVCodecContext 的指针,包含解码器的上下文信息。
poutbuf : 输出缓冲区的指针,解析出的完整帧将被存储在这里。
poutbuf_size : 输出缓冲区的大小,以字节为单位。
buf : 输入缓冲区的指针,包含需要解析的原始数据。
buf_size : 输入缓冲区的大小,以字节为单位。
pts : 输入数据包的演示时间戳(presentation timestamp)。
dts : 输入数据包的解码时间戳(decoding timestamp)。
pos : 输入数据包在文件中的位置。*/
//通过0001 截断输出到AVPacket 返回帧大小
int ret = av_parser_parse2(parser, c,
&pkt->data, &pkt->size, //输出
data, data_size, //输入
AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0
);//返回消耗的输入数据字节数ret。如果所有输入数据都被消耗,则返回值等于 buf_size。如果解析过程中出现错误,则返回负数。
data += ret;
data_size -= ret; //待处理的数据大小
if (pkt->size)
{
cout << pkt->size << " " << flush;
}
}
}
av_packet_free(&pkt);
getchar();
return 0;
}