如何切断与FFmpeg的C API视频 [英] How to cut video with FFmpeg C API

查看:285
本文介绍了如何切断与FFmpeg的C API视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我怎么能砍视频FFmpeg的C API?从00:10:00至00:20:00为例。
我需要什么样的功能使用?

我在使用此功能转换视频:

 转换为int(字符*文件){
    AVFrame *帧;
    AVPacket inPacket,outPacket;    如果(avio_open(安培; outFormatContext-> PB,文件AVIO_FLAG_WRITE)小于0){
        fprintf中(标准错误,转换():无法打开了所有的文件\\ n);
        返回0;
    }    avformat_write_header(outFormatContext,NULL);
    帧= AV codec_alloc_frame();
    av_init_packet(安培; inPacket);    而(av_read_frame(inFormatContext,&安培; inPacket)> = 0){
        如果(inPacket.stream_index == inVideoStreamIndex){
            AV codec_de code_video2(在codecContext,框架,和放大器; frameFinished,&安培; inPacket);
            如果(frameFinished){
                av_init_packet(安培; outPacket);
                AV codec_en code_video2(出codecContext,&安培; outPacket,架,&安培;所输出的);
                如果(所输出的){
                    如果(av_write_frame(outFormatContext,&放大器;!outPacket)= 0){
                        fprintf中(标准错误,转换():错误而写的视频帧\\ n);
                        返回0;
                    }
                }
                av_free_packet(安培; outPacket);
            }
        }
    }    av_write_trailer(outFormatContext);
    av_free_packet(安培; inPacket);
    返回1;
}


解决方案

如果您只想剪切视频,你不需要颖code中的视频,如果你想要的。
所以我假设你想要的切割和颖code 出于某种原因。因此,根据您的code

注意,您必须拥有访问视频 AVStream * 结构......我把它命名为 inVideoStream

  INT convert_and_cut(字符*文件,开始时间浮动,浮动结束时间){
    AVFrame *帧;
    AVPacket inPacket,outPacket;    如果(avio_open(安培; outFormatContext-> PB,文件AVIO_FLAG_WRITE)小于0){
        fprintf中(标准错误,转换():无法打开了所有的文件\\ n);
        返回0;
    }    //求你希望的开始时间。
    // 开始
    AVRational default_timebase;
    default_timebase.num = 1;
    default_timebase.den = AV_TIME_BASE;    //假设你有机会获得该课程的inVideoStream
    starttime_int64的int64_t = av_rescale_q((的int64_t)(开始时间* AV_TIME_BASE),default_timebase,inVideoStream->那么time_base);
    endtime_int64的int64_t = av_rescale_q((的int64_t)(结束时间* AV_TIME_BASE),default_timebase,inVideoStream->那么time_base);    如果(avformat_seek_file(inFormatContext,inVideoStreamIndex,INT64_MIN,starttime_int64,INT64_MAX,0)℃,){
        //错误...做些什么...
        返回0; // 0通常用于在C的成功,但我下面的code。
    }    AV codec_flush_buffers(inVideoStream-> codeC);
    // 结束    avformat_write_header(outFormatContext,NULL);
    帧= AV codec_alloc_frame();
    av_init_packet(安培; inPacket);    //你使用avformat_seek_file()寻求接近你想要点......为了给precision你的寻求,
    //只是去读取数据包并检查包PTS(presentation时间戳)
    而(av_read_frame(inFormatContext,&安培; inPacket)> = 0){
        如果(inPacket.stream_index == inVideoStreamIndex){
            AV codec_de code_video2(在codecContext,框架,和放大器; frameFinished,&安培; inPacket);
            //这一行,保证你得到你真正想要的。
            如果(frameFinished&安培;&安培;框架> pkt_pts> = starttime_int64和放大器;&安培;框架> pkt_pts< = endtime_int64){
                av_init_packet(安培; outPacket);
                AV codec_en code_video2(出codecContext,&安培; outPacket,架,&安培;所输出的);
                如果(所输出的){
                    如果(av_write_frame(outFormatContext,&放大器;!outPacket)= 0){
                        fprintf中(标准错误,转换():错误而写的视频帧\\ n);
                        返回0;
                    }
                }
                av_free_packet(安培; outPacket);
            }            //退出循环,如果你得到了你想要的帧。
            如果(框架> pkt_pts> endtime_int64){
                打破;
            }
        }
    }    av_write_trailer(outFormatContext);
    av_free_packet(安培; inPacket);
    返回1;
}

How can I cut video with FFmpeg C API? From 00:10:00 to 00:20:00 for example. What functions I need to use?

I convert video using this function:

int convert(char *file) {
    AVFrame *frame;
    AVPacket inPacket, outPacket;

    if(avio_open(&outFormatContext->pb, file, AVIO_FLAG_WRITE) < 0) {
        fprintf(stderr, "convert(): cannot open out file\n");
        return 0;
    }

    avformat_write_header(outFormatContext, NULL);
    frame = avcodec_alloc_frame();
    av_init_packet(&inPacket);

    while(av_read_frame(inFormatContext, &inPacket) >= 0) {
        if(inPacket.stream_index == inVideoStreamIndex) {
            avcodec_decode_video2(inCodecContext, frame, &frameFinished, &inPacket);
            if(frameFinished) {
                av_init_packet(&outPacket);
                avcodec_encode_video2(outCodecContext, &outPacket, frame, &outputed);
                if(outputed) {
                    if (av_write_frame(outFormatContext, &outPacket) != 0) {
                        fprintf(stderr, "convert(): error while writing video frame\n");
                        return 0;
                    }
                }
                av_free_packet(&outPacket);
            }
        }
    }

    av_write_trailer(outFormatContext);
    av_free_packet(&inPacket);
    return 1;
}

解决方案

If you just wanna cut the video, you don't need to reencode the video if you want. So I am supposing you wanna cut and reencode for some reason. So, based on your code:

Observe you must to have access to the video AVStream* structure... I named it as inVideoStream.

int convert_and_cut(char *file, float starttime, float endtime) {
    AVFrame *frame;
    AVPacket inPacket, outPacket;

    if(avio_open(&outFormatContext->pb, file, AVIO_FLAG_WRITE) < 0) {
        fprintf(stderr, "convert(): cannot open out file\n");
        return 0;
    }

    // seek to the start time you wish.
    // BEGIN
    AVRational default_timebase;
    default_timebase.num = 1;
    default_timebase.den = AV_TIME_BASE;

    // suppose you have access to the "inVideoStream" of course
    int64_t starttime_int64 = av_rescale_q((int64_t)( starttime * AV_TIME_BASE ), default_timebase, inVideoStream->time_base);
    int64_t endtime_int64 = av_rescale_q((int64_t)( endtime * AV_TIME_BASE ), default_timebase, inVideoStream->time_base);

    if(avformat_seek_file(inFormatContext, inVideoStreamIndex, INT64_MIN, starttime_int64, INT64_MAX, 0) < 0) {
        // error... do something...
        return 0; // usually 0 is used for success in C, but I am following your code.
    }

    avcodec_flush_buffers( inVideoStream->codec );
    // END

    avformat_write_header(outFormatContext, NULL);
    frame = avcodec_alloc_frame();
    av_init_packet(&inPacket);

    // you used avformat_seek_file() to seek CLOSE to the point you want... in order to give precision to your seek,
    // just go on reading the packets and checking the packets PTS (presentation timestamp) 
    while(av_read_frame(inFormatContext, &inPacket) >= 0) {
        if(inPacket.stream_index == inVideoStreamIndex) {
            avcodec_decode_video2(inCodecContext, frame, &frameFinished, &inPacket);
            // this line guarantees you are getting what you really want.
            if(frameFinished && frame->pkt_pts >= starttime_int64 && frame->pkt_pts <= endtime_int64) {
                av_init_packet(&outPacket);
                avcodec_encode_video2(outCodecContext, &outPacket, frame, &outputed);
                if(outputed) {
                    if (av_write_frame(outFormatContext, &outPacket) != 0) {
                        fprintf(stderr, "convert(): error while writing video frame\n");
                        return 0;
                    }
                }
                av_free_packet(&outPacket);
            }

            // exit the loop if you got the frames you want.
            if(frame->pkt_pts > endtime_int64) {
                break;
            }
        }
    }

    av_write_trailer(outFormatContext);
    av_free_packet(&inPacket);
    return 1;
}

这篇关于如何切断与FFmpeg的C API视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆