将某一个视频文件的每一帧都拆分出来保存成一个独立的文件,如果需要修改I帧,则可以通过FFmpeg修改文件的GOP大小,命令行如下:
ffmpeg -i video.mp4 -g 10 gop10.mp4
再提取之前需要先做一件事,那就是需要将视频文件改为ES流:
ffmpeg -i gop10.mp4 -vcodec copy -an -f rawvideo -vbsf h264_mp4toannexb es.raw
这个时候就可以用代码将文件拆分出来了,代码如下:(我用的是海思的算法)
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int GetVideoFrame(FILE *fp, char **pBuf, int &nBufLen)
{
bool bLoopSend = false;
bool bFindStart = false;
bool bFindEnd = false;
long s32UsedBytes = 0;
long iStart = 0;
char *pu8Addr = NULL;
int i = 0;
int MaxCount = 1024 * 512;
static long framePos = 0;
int frameLen = 0;
if (fp == NULL)
{
return -2;
}
char *pu8Buf = (char *)malloc(MaxCount);
if (pu8Buf == NULL)
{
free(pu8Buf);
pu8Buf = NULL;
if (fp != NULL)
{
fclose(fp);
fp = NULL;
}
return -2;
}
fseek(fp, framePos, SEEK_SET);
frameLen = fread(pu8Buf, 1, MaxCount, fp);
if (frameLen == 0)
{
framePos = 0;
fseek(fp, framePos, SEEK_SET);
frameLen = fread(pu8Buf, 1, MaxCount, fp);
if (frameLen == 0)
{
nBufLen = 0;
free(pu8Buf);
pu8Buf = NULL;
if (fp != NULL)
{
fclose(fp);
fp = NULL;
}
return -1;
}
}
else if (frameLen == -1)
{
nBufLen = -1;
free(pu8Buf);
pu8Buf = NULL;
if (fp != NULL)
{
fclose(fp);
fp = NULL;
}
return -1;
}
for (i = 0; i < frameLen - 8; i++)
{
int tmp = pu8Buf[i + 3] & 0x1F;
if (pu8Buf[i] == 0 && pu8Buf[i + 1] == 0 && pu8Buf[i + 2] == 1 &&
(
((tmp == 5 || tmp == 1) && ((pu8Buf[i + 4] & 0x80) == 0x80)) ||
(tmp == 20 && (pu8Buf[i + 7] & 0x80) == 0x80)
)
)
{
iStart = i;
bFindStart = true;
i += 8;
break;
}
}
for (; i < frameLen - 8; i++)
{
int tmp = pu8Buf[i + 3] & 0x1F;
if (pu8Buf[i] == 0 && pu8Buf[i + 1] == 0 && pu8Buf[i + 2] == 1 &&
(
tmp == 15 || tmp == 7 || tmp == 8 || tmp == 6 ||
((tmp == 5 || tmp == 1) && ((pu8Buf[i + 4] & 0x80) == 0x80)) ||
(tmp == 20 && (pu8Buf[i + 7] & 0x80) == 0x80)
)
)
{
bFindEnd = true;
break;
}
}
if (i > 0)
frameLen = i;
if (!bFindStart)
{
printf(" can not find start code! \n");
}
else if (!bFindEnd)
{
frameLen = i + 8;
}
pu8Addr = pu8Buf;
memcpy(*pBuf, pu8Addr, frameLen);
nBufLen = frameLen;
framePos = framePos + frameLen;
free(pu8Buf);
pu8Buf = NULL;
return 0;
}
int EncodeH264File()
{
while (1)
{
#if 1
static int fnum = 0;
fnum++;
static FILE *fp = NULL;
FILE *fps = NULL;
char fname[10];
static int nIndex = 0;
sprintf(fname, "%d.h264", fnum);
fps = fopen("es.raw", "rb");
if (!fps)
{
//continue;
return -1;
}
#if 0//20180814 wll
nIndex++;
char *str = "test.h264";
if (nIndex == 1)
#endif
{
fp = fopen(fname, "wb");
if (!fp)
{
//continue;
return -1;
}
}
char *str = (char *)malloc(1024 * 512);
int bufLen = 0;
GetVideoFrame(fps, &str, bufLen);
fwrite(str, bufLen, 1, fp);
#if 0//20180814 wll
#else
fclose(fp);
fp = NULL;
#endif
#endif
}
}
int main(int argc, char *argv[])
{
EncodeH264File();
system("pause");
return 0;
}
直接vs直接运行就可以了,我拆分出来的如下:
如上图就是我拆分出来的,上面哟的那个红色标记出来的是关键帧,因为我设置的GOP为10,所以每10帧就会有一个关键帧