ffmpeg裁剪视频

使用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;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值