如何切断与FFmpeg的C API视频 [英] How to cut video with FFmpeg C API
本文介绍了如何切断与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屋!
查看全文