使用ffmpeg裁剪一段视频主要需要一下几步
1、avformat_open_input /* 打开输入文件 */
2、avformat_alloc_output_context2 /* 打开输出文件 */
3、avformat_new_stream /* 为输出文件创建流 */
4、avcodec_copy_context && avcodec_parameters_copy /* 拷贝流参数 */
5、avformat_write_header /* 写多媒体文件头 */
6、av_seek_frame /* 定位到裁剪时间点 */
7、av_read_frame /* 读数据 */
8、av_interleaved_write_frame /* 写数据 */
9、判断裁剪时间
10、av_write_trailer /* 写多媒体文件尾 */
源码
#include <stdio.h>
#include <stdlib.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
int cutVideo(int startTime, int endTime, const char *pSrc, const char *pDst)
{
AVFormatContext *pInAVFmtCtx = NULL;
AVFormatContext *pOutAVFmtCtx = NULL;
AVOutputFormat *pOutAVFmt = NULL;
AVPacket pkt;
int ret;
int i;
int isOpen = 0;
/* 打开输入多媒体文件 */
if ((ret = avformat_open_input(&pInAVFmtCtx, pSrc, 0, 0)) < 0)
{
printf("avformat_open_input error!\n");
goto end;
}
/* 打印输入多媒体文件的信息 */
av_dump_format(pInAVFmtCtx, 0, pSrc, 0);
/* 打开输出文件 */
avformat_alloc_output_context2(&pOutAVFmtCtx, NULL, NULL, pDst);
if (!pOutAVFmtCtx)
{
printf("avformat_alloc_output_context2 error!\n");
ret = AVERROR_UNKNOWN;
goto end;
}
pOutAVFmt = pOutAVFmtCtx->oformat;
/* 为输出多媒体文件创建流并且拷贝流参数 */
for(i = 0; i < pInAVFmtCtx->nb_streams; i++)
{
AVStream *pInStream = pInAVFmtCtx->streams[i];
AVStream *pOutStream = avformat_new_stream(pOutAVFmtCtx, pInStream->codec->codec);;
if (!pOutStream)
{
printf("avformat_new_stream error!\n");
ret = AVERROR_UNKNOWN;
goto end;
}
/* 拷贝参数 */
ret = avcodec_copy_context(pOutStream->codec, pInStream->codec);
if (ret < 0)
{
printf("avcodec_copy_context error!\n");
goto end;
}
/* 拷贝参数 */
ret = avcodec_parameters_copy(pOutStream->codecpar, pInStream->codecpar);
if(ret < 0)
{
printf("avcodec_parameters_copy error!\n");
return -1;
}
pOutStream->codec->codec_tag = 0;
}
av_dump_format(pOutAVFmtCtx, 0, pDst, 1);
/* 打开输出多媒体文件,准备写数据 */
ret = avio_open(&pOutAVFmtCtx->pb, pDst, AVIO_FLAG_WRITE);
if (ret < 0)
{
printf("avio_open error!\n");
goto end;
}
isOpen = 1;
/* 写多媒体文件头 */
ret = avformat_write_header(pOutAVFmtCtx, NULL);
if (ret < 0)
{
printf("avformat_write_header error!\n");
goto end;
}
/* 移动到相应的时间点 */
ret = av_seek_frame(pInAVFmtCtx, -1, startTime*AV_TIME_BASE, AVSEEK_FLAG_ANY);
if (ret < 0)
{
printf("av_seek_frame error!\n");
goto end;
}
int64_t *dtsStartTime = malloc(sizeof(int64_t) * pInAVFmtCtx->nb_streams);
memset(dtsStartTime, 0, sizeof(int64_t) * pInAVFmtCtx->nb_streams);
int64_t *ptsStartTime = malloc(sizeof(int64_t) * pInAVFmtCtx->nb_streams);
memset(ptsStartTime, 0, sizeof(int64_t) * pInAVFmtCtx->nb_streams);
while(1)
{
AVStream *pInStream, *pOutStream;
ret = av_read_frame(pInAVFmtCtx, &pkt);
if (ret < 0)
break;
pInStream = pInAVFmtCtx->streams[pkt.stream_index];
pOutStream = pOutAVFmtCtx->streams[pkt.stream_index];
if (av_q2d(pInStream->time_base) * pkt.pts > endTime)
{
av_free_packet(&pkt);
break;
}
if (dtsStartTime[pkt.stream_index] == 0)
dtsStartTime[pkt.stream_index] = pkt.dts;
if (ptsStartTime[pkt.stream_index] == 0)
ptsStartTime[pkt.stream_index] = pkt.pts;
/* 转化时间基 */
pkt.pts = av_rescale_q_rnd(pkt.pts - ptsStartTime[pkt.stream_index], pInStream->time_base, pOutStream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
pkt.dts = av_rescale_q_rnd(pkt.dts - dtsStartTime[pkt.stream_index], pInStream->time_base, pOutStream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
if (pkt.pts < 0)
pkt.pts = 0;
if (pkt.dts < 0)
pkt.dts = 0;
pkt.duration = (int)av_rescale_q((int64_t)pkt.duration, pInStream->time_base, pOutStream->time_base);
pkt.pos = -1;
/* 写数据 */
ret = av_interleaved_write_frame(pOutAVFmtCtx, &pkt);
if (ret < 0)
{
printf("av_interleaved_write_frame error!\n");
break;
}
av_free_packet(&pkt);
}
free(dtsStartTime);
free(ptsStartTime);
av_write_trailer(pOutAVFmtCtx);
end:
if(isOpen)
avio_closep(&pOutAVFmtCtx->pb);
if(pInAVFmtCtx)
avformat_close_input(&pInAVFmtCtx);
if(pOutAVFmtCtx)
avformat_free_context(pOutAVFmtCtx);
return ret;
}
/*
argv[1]:起始时间
argv[2]:终止时间
argv[3]:输入多媒体文件
argv[4]:输出多媒体文件
*/
int main(int argc, char *argv[])
{
if(argc < 5)
{
printf("arg error!\n");
return -1;
}
int startTime = atoi(argv[1]);
int endTime = atoi(argv[2]);
const char *pSrc = argv[3];
const char *pDst = argv[4];
av_register_all();
cutVideo(startTime, endTime, pSrc, pDst);
return 0;
}