Qt开发笔记之编码h264码流并封装mp4
前言
前面尝试在windows下编译,实在过不了,只好转战至ubuntu。
Ubuntu下mp4v2库编译
步骤一:下载、放入编译文件夹并解压
步骤二:配置configre
步骤三:编译make,错误‘\0’
直接修改下源码
继续编译。
Demo演示
H264转mp4
注意:转换后的结果不对,原来效果为:
笔者尝试至少4套不同人封装的mp4v2代码,以及将视频文件给到专做视频的使用mp4v2结果也是一样,没有再深入去研究,欢迎读者解决该问题,笔者后续有时间会继续研究。
使用ffmpeg命令转mp4是正常的,转换指令如下:
ffmpeg -i cuc_ieschool_640x360_yuv420p.h264 -vcodec copy -f mp4 1.mp4
关键代码
bool X264Manager::testH264ToMp4(QString h264File, QString destFile)
{
bool ret = false;
// 检测输入文件
if(!h264File.endsWith(".h264"))
{
qDebug() << __FILE__ << __LINE__ << "Failed to recgnize ext:" << h264File;
return ret;
}
// 检测输出文件
if(destFile.isEmpty())
{
destFile = h264File;
destFile.truncate(destFile.lastIndexOf(".yuv"));
destFile += ".mp4";
}else if(!destFile.endsWith(".mp4"))
{
qDebug() << __FILE__ << __LINE__ << "Failed to recgnize ext:" << destFile;
return ret;
}
qDebug() << __FILE__ << __LINE__ << h264File << "to" << destFile;
FILE *pIn = NULL;
unsigned char *pBuf = (unsigned char *)malloc(1024*1024);
unsigned char *pBuf2 = (unsigned char *)malloc(1024*1024);
unsigned char *pNalu = NULL;
unsigned char naluType;
int len;
int num = 0;
MP4FileHandle pHandle = NULL;
MP4TrackId videoId;
int width = 640;
int height = 360;
int frameRate = 25;
// int timeScale = 9600;
int timeScale = 1000;
int addStream = 1;
// 打开.h264流文件
pIn = fopen(h264File.toUtf8().data(), "rb");
if(!pIn)
return -1;
// 创建mp4文件
pHandle = MP4Create(destFile.toUtf8().data(), 0);
// pHandle = MP4CreateEx(destFile.toUtf8().data(), 0, 1, 1, 0, 0, 0, 0);
if(pHandle == MP4_INVALID_FILE_HANDLE)
{
printf("ERROR:Create mp4 handle fialed.\n");
return -1;
}
// 设置timescale
MP4SetTimeScale(pHandle, timeScale);
while(1)
{
len = getNalu(pIn, pBuf);
{
printf("len(%d)\n", len);
}
if (len <= 0)
break;
if (pBuf[0] != 0 || pBuf[1] != 0 || pBuf[2] != 0 || pBuf[3] != 1)
continue;
len -= 4;
pNalu = pBuf+4;
naluType = pNalu[0]&0x1F;
switch (naluType)
{
case 0x07: // SPS
printf("------------------------------------\n");
printf("sps(%d)\n", len);
if (addStream)
{
videoId = MP4AddH264VideoTrack
(pHandle,
timeScale, // 一秒钟多少timescale
timeScale/frameRate, // 每个帧有多少个timescale
width, // width
height, // height
pNalu[1], // sps[1] AVCProfileIndication
pNalu[2], // sps[2] profile_compat
pNalu[3], // sps[3] AVCLevelIndication
3); // 4 bytes length before each NAL unit
if (videoId == MP4_INVALID_TRACK_ID)
{
printf("Error:Can't add track.\n");
return -1;
}
MP4SetVideoProfileLevel(pHandle, 0x7F);
addStream = 0;
}
MP4AddH264SequenceParameterSet(pHandle, videoId, pNalu, len);
break;
case 0x08: // PPS
// printf("pps(%d)\n", len);
MP4AddH264PictureParameterSet(pHandle, videoId, pNalu, len);
break;
default:
memcpy(pBuf + 4, pBuf, len);
pBuf[0] = (len>>24)&0xFF;
pBuf[1] = (len>>16)&0xFF;
pBuf[2] = (len>>8)&0xFF;
pBuf[3] = (len>>0)&0xFF;
printf("slice(%d, %d, %d, %d)(%d, %d, %d, %d)\n", \
pBuf[0], pBuf[1], pBuf[2], pBuf[3], pBuf[4], \
pBuf[5], pBuf[6], pBuf[7]);
MP4WriteSample(pHandle, videoId, pBuf, len+4,\
MP4_INVALID_DURATION, 0, 1);
break;
}
}
free(pBuf);
fclose(pIn);
MP4Close(pHandle, 0);
}
结论
可能换一个mp4库尝试,验证一下。
入坑一:封装出的mp4文件出现马赛克或者模糊的情况。
尝试:
自己写代码,网上代码,自己对比文件(读者有兴趣可以弄,暂未弄),暂未解决。
解决方法:
暂未解决,有时间再弄,短期内决定尝试换一个库,同样期待大佬定位并解决mp4v2库这个问题,解决了欢迎联系笔者:QQ21497936,提供解决方法。
本文同步分享在 博客“红胖子(AAA红模仿)”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。