ffmpeg日记4001-原理介绍-视频切割原理

原理

打开输入---->打开输出---->根据输入来创建流---->拷贝流设置---->循环读帧---->判断时间点是否到达切割点,并做设置---->设置pts和dts---->写入---->善后

重点是pts和dts如何设置。参考《ffmpeg学习日记25-pts,dts概念的理解》

在这里插入图片描述

示例代码

CMakeLists.txt

cmake_minimum_required(VERSION 3.14)project(clipVideo )#set(CMAKE_CXX_STANDARD 11)
#set(CMAKE_CXX_STANDARD_REQUIRED YES)set(CMAKE_AUTOMOC ON) # Meta-Object Compiler
set(CMAKE_AUTORCC ON) # Resource Compiler
set(CMAKE_AUTOUIC ON) # User Interface Compilerset(CMAKE_BUILD_TYPE Debug)#find_package(PkgConfig REQUIRED)
#pkg_check_modules(AVLIB REQUIRED IMPORTED_TARGET libavcodec libavformat libavutil libswresample libswscale)if(CMAKE_SYSTEM_NAME MATCHES "Linux")set(CURRENT_SYSTEM Linux)
elseif(CMAKE_SYSTEM_NAME MATCHES "Windows")set(CURRENT_SYSTEM Windows)
endif()set(FFMPEG_LIB_DIR ${PROJECT_SOURCE_DIR}/../../lib)
set(FFMPEG_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/../../include)include_directories(${PROJECT_SOURCE_DIR}
#    ${PROJECT_SOURCE_DIR}/../../include${FFMPEG_INCLUDE_DIR})link_libraries(
#    ${PROJECT_SOURCE_DIR}/../../lib${FFMPEG_LIB_DIR})#对于find_package找不到的外部依赖库,可以用add_library添加
# SHARED表示添加的是动态库
# IMPORTED表示是引入已经存在的动态库add_library( avcodec STATIC IMPORTED)
add_library( avfilter STATIC IMPORTED )
add_library( swresample STATIC IMPORTED )
add_library( swscale STATIC IMPORTED )
add_library( avformat STATIC IMPORTED )
add_library( avutil STATIC IMPORTED )#指定所添加依赖库的导入路径
set_target_properties( avcodec PROPERTIES IMPORTED_LOCATION ${FFMPEG_LIB_DIR}/avcodec.lib )
set_target_properties( avfilter PROPERTIES IMPORTED_LOCATION ${FFMPEG_LIB_DIR}/avfilter.lib )
set_target_properties( swresample PROPERTIES IMPORTED_LOCATION ${FFMPEG_LIB_DIR}/swresample.lib )
set_target_properties( swscale PROPERTIES IMPORTED_LOCATION ${FFMPEG_LIB_DIR}/swscale.lib )
set_target_properties( avformat PROPERTIES IMPORTED_LOCATION ${FFMPEG_LIB_DIR}/avformat.lib )
set_target_properties( avutil PROPERTIES IMPORTED_LOCATION ${FFMPEG_LIB_DIR}/avutil.lib )add_executable(${PROJECT_NAME} main.cpp)target_link_libraries(${PROJECT_NAME}avcodec avfilter avformat avutil
#    postproc swresample swscale)

main.cpp

#include <iostream>
#include <cinttypes>#ifdef __cplusplus
extern "C" {
#endif#include <stdio.h>
#include "libavutil/avutil.h"#include <libavcodec/avcodec.h>#include <libavformat/avformat.h>
#include <libavformat/avio.h>#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>#include <libavutil/timestamp.h>#include <libavutil/time.h>
#include <libavutil/pixdesc.h>
#include <libavutil/audio_fifo.h>
#include <libavutil/avassert.h>
#include <libavutil/avstring.h>
#include <libavutil/frame.h>
#include <libavutil/opt.h>#include <libswresample/swresample.h>#ifdef __cplusplus
}
#endif#ifdef _WIN32
#include <direct.h>
#elif __APPLE__ || __linux__
#include<unistd.h>
#endifusing namespace std;int main()
{cout << "Hello World!" << endl;printf("ffmpeg version:%s\n",av_version_info());std::cout << "current path:" << getcwd(NULL,0) << std::endl;int ret = 0;float fromSeconds = 3.0,endSeconds = 8.0;AVFormatContext *ifmt_ctx = NULL,*ofmt1_ctx = NULL;std::string ifileName = "../../../15s.mp4",ofileName1 = "1.mp4";AVPacket pkt;if ( (ret = avformat_open_input(&ifmt_ctx,ifileName.c_str(),NULL,NULL)) < 0){std::cout << "can not open the in put file format context!" << std::endl;return 0;}if( (ret = avformat_find_stream_info(ifmt_ctx,NULL)) < 0){std::cout << "can not find the input stream info" << std::endl;return 0;}avformat_alloc_output_context2(&ofmt1_ctx,NULL,NULL,ofileName1.c_str());if(!ofmt1_ctx){std::cout << "could not creat output1 context" << std::endl;return 0;}//拷贝参数到输出结构for(int i = 0;i < ifmt_ctx->nb_streams;i++){AVStream *instream = ifmt_ctx->streams[i];AVCodec *codec = avcodec_find_decoder(instream->codecpar->codec_id);AVStream *outStream = avformat_new_stream(ofmt1_ctx,codec);if(!outStream){std::cout << "failed allow output stream" << std::endl;return 0;}AVCodecContext *codecCtx = avcodec_alloc_context3(codec);ret = avcodec_parameters_to_context(codecCtx,instream->codecpar);if(ret < 0){std::cout << "failed to copy instream codecpar to codec context" << std::endl;return 0;}//这一步是在干什么呢codecCtx->codec_tag = 0;//这个标志是什么意思???if (ofmt1_ctx->oformat->flags & AVFMT_GLOBALHEADER){codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;}ret = avcodec_parameters_from_context(outStream->codecpar,codecCtx);if (ret < 0){std::cout << "failed to copy codec context to outstram codecpar context" << std::endl;return 0;}}av_dump_format(ofmt1_ctx,0,ofileName1.c_str(),1);if(!(ofmt1_ctx->flags & AVFMT_NOFILE)){ret = avio_open(&ofmt1_ctx->pb,ofileName1.c_str(),AVIO_FLAG_WRITE);if (ret < 0){std::cout << "could not open output 1.mp4" << std::endl;return 0;}}//写文件头ret = avformat_write_header(ofmt1_ctx,NULL);if (ret < 0){std::cout << "error write header of 1.mp4" << std::endl;return 0;}ret = av_seek_frame(ifmt_ctx, -1, (int64_t)(fromSeconds * AV_TIME_BASE), AVSEEK_FLAG_ANY);std::cout << "ret:" << ret << std::endl;int64_t *dstStartFrom = (int64_t *)malloc(sizeof(int64_t) * ifmt_ctx->nb_streams);memset(dstStartFrom, 0, sizeof(int64_t) * ifmt_ctx->nb_streams);int64_t *ptsStartFrom = (int64_t *)malloc(sizeof(int64_t) * ifmt_ctx->nb_streams);memset(ptsStartFrom, 0, sizeof(int64_t) * ifmt_ctx->nb_streams);while(1){AVStream *instream,*outstream;ret = av_read_frame(ifmt_ctx,&pkt);if (ret < 0)break;std::cout << "pkt.pts:" << pkt.pts << std::endl;instream = ifmt_ctx->streams[pkt.stream_index];outstream = ofmt1_ctx->streams[pkt.stream_index];if (av_q2d(instream->time_base) * pkt.pts > endSeconds){av_packet_unref(&pkt);break;}if (dstStartFrom[pkt.stream_index] == 0){dstStartFrom[pkt.stream_index] = pkt.dts;
//          /  printf("dstStartFrom: %s\n", av_strerror(dstStartFrom[pkt.stream_index]));}if (ptsStartFrom[pkt.stream_index] == 0){ptsStartFrom[pkt.stream_index] = pkt.dts;
//            printf("ptsStartFrom: %s\n", av_strerror(ptsStartFrom[pkt.stream_index]));}pkt.pts = av_rescale_q_rnd(pkt.pts - ptsStartFrom[pkt.stream_index],instream->time_base,outstream->time_base,(enum AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX) );//pkt.dts = av_rescale_q_rnd(pkt.dts - dstStartFrom[pkt.stream_index],instream->time_base,outstream->time_base,(enum AVRounding)(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 ,instream->time_base,outstream->time_base);pkt.pos = -1;ret = av_interleaved_write_frame(ofmt1_ctx,&pkt);if(ret){std::cout << "error muxing packet" << std::endl;break;}av_packet_unref(&pkt);}//写文件尾free(dstStartFrom);free(ptsStartFrom);av_write_trailer(ofmt1_ctx);//释放资源avformat_close_input(&ifmt_ctx);if (ofmt1_ctx && !(ofmt1_ctx->flags & AVFMT_NOFILE)){avio_closep(&ofmt1_ctx->pb);}avformat_free_context(ofmt1_ctx);return 0;
}

总结

  1. 这里的操作是将一种视频格式切割,之后生成的视频是同样的格式,所以直接是参数的复制即可,如果要生成另一种格式的视频,应该要单独设置设置输出视频格式的参数。

参考

  • ffmpeg实现视频切割

  • FFmpeg ‘avcodec_copy_context’ deprecated (视频裁剪)

  • av_seek_frame使用详解

  • FFmpeg中的时间基(time_base), AV_TIME_BASE

  • FFmpeg之时间戳详解


  • 在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/738096.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ftp速度太慢只有几十k,怎么解决?

FTP是目前许多企业日常运营中还在用的文件传输方式。虽然比较普遍&#xff0c;然而&#xff0c;许多用户在使用FTP时经常遇到速度缓慢的问题&#xff0c;有时甚至只有几十KB/s。这不仅影响工作效率&#xff0c;还可能导致许多数据传输的延迟的问题。本文将探讨FTP速度慢的原因&…

计算机服务器中了faust勒索病毒怎么解密,faust勒索病毒解密工具流程

在互联网飞速发展的今天&#xff0c;越来越多的企业走向了数字化办公模式&#xff0c;许多企业开始利用网络计算机开展各项工作业务&#xff0c;网络也为企业的生产效率提供了极大便利&#xff0c;但网络中存在许多恶意威胁。近日&#xff0c;云天数据恢复中心接到许多企业的求…

Java 学习和实践笔记(34):对象的转型(casting)

对象的转型&#xff08;casting)有两种&#xff0c;一种是向上转型&#xff0c;一种是向下转型。 向上转型&#xff1a;父类引用指向子类对象。这属于自动类型转换&#xff0c;编译器会自动完成。 上一节的多态中&#xff0c;形参为父类Animal, 但是调用时实参为子类对象Dog&…

linux中查看并修改日期

1.如何在终端控制行界面显示并且调整日期&#xff1a; 显示当前日期&#xff1a; 2.显示当前年份&#xff1a; 3.显示当前月份&#xff1a; 4.显示当前天数&#xff1a; 5.显示到目前为止的天数&#xff1a; 6.显示日期&#xff1a; date “%x“ ≈ date ”%Y %m %d"…

09-设计模式 面试题

你之前项目中用过设计模式吗? 工厂方法模式分类 简单工厂模式工厂方法模式抽象工厂模式工厂模式 需求:设计一个咖啡店点餐系统。 设计一个咖啡类(Coffee),并定义其两个子类(美式咖啡【AmericanCoffee】和拿铁咖啡【LatteCoffee】);再设计一个咖啡店类(CoffeeStore)…

一、什么是 HarmonyOS ?

HarmonyOS 是华为开发的一款面向未来的全场景分布式智慧操作系统&#xff0c;将逐步覆盖 18N 全场景终端设备。 对消费者而言&#xff0c;HarmonyOS 用一个“统一的软件系统”&#xff0c;从根本上解决消费者面对大量智能终端体验割裂的问题&#xff0c;为消费者带来统一、便利…

Kafka Stream入门

1. 什么是流式计算 流式计算&#xff08;Stream Processing&#xff09;是一种计算模型&#xff0c;旨在处理连续的数据流。与传统的批处理模型不同&#xff0c;流式计算可以实时或接近实时地处理和分析数据&#xff0c;这意味着数据在生成后不久就被处理&#xff0c;而不是存…

基于android的物业管理系统的设计与实现19.8

目录 基于android的物业管理系统的设计与实现 3 摘 要 3 Android property managemengt system 5 Abstract 5 1 绪论 6 1.1 选题背景 6 1.2 课题研究现状 6 1.3 设计研究主要内容 7 1.4 系统主要设计思想 8 2 开发环境 8 2.1 Android系统的结构 8 图2-1 Android系统架构图 9 2…

Python绘图-14绘制3D图(下)

14.7绘制3D等高线图个性化colormap 14.7.1图像呈现 14.7.2绘图代码 import numpy as np # 导入numpy库&#xff0c;numpy是Python的一个强大的数值计算扩展程序库&#xff0c;支持大量的维度数组与矩阵运算。 import matplotlib.pyplot as plt # 导入matplotlib的绘图模块p…

UDP编程及特点

目录 1.UDP编程流程 2.recvfrom()、sento() 3.代码演示 3.udp特点 1.UDP编程流程 socket()用来创建套接字&#xff0c;使用 udp 协议时&#xff0c;选择数据报服务 SOCK_DGRAM。sendto()用来发送数据&#xff0c;由于 UDP 是无连接的&#xff0c;每次发送数据都需要指定对端…

神经网络基本使用

1. 卷积层 convolution layers import torch import torchvision from torch import nn from torch.nn import Conv2d from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriterdataset torchvision.datasets.CIFAR10(./dataset,trainFa…

Aspose.Words指定位置插入table

如果在创建书签&#xff0c;然后在书签位置插入表格&#xff0c;会出现格式错乱&#xff0c;在单元格位置里面有一个表格&#xff0c;不符合实际使用。正确做法是复制模板文件里面的表格行&#xff0c;然后插入若干行。 如图标记红色位置插入动态数据行&#xff0c;是先复制标…

day1_C++:实现C++风格字符串输出

1.提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数&#xff0c;要求使用C风格字符串完成 程序代码&#xff1a; #include <iostream>//标准输入输出流 #include <string.h>//C中字符串相关头文件 using na…

HBase分布式数据库的原理和架构

一、HBase简介 HBase是是一个高性能、高可靠性、面向列的分布式数据库&#xff0c;它是为了在廉价的硬件集群上存储大规模数据而设计的。HBase利用Hadoop HDFS作为其文件存储系统&#xff0c;且Hbase是基于Zookeeper的。 二、HBase架构 *图片引用 Hbase采用Master/Slave架构…

LeetCode226题:翻转二叉树(python3)

class Solution:def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:if not root:return rootleft self.invertTree(root.left)right self.invertTree(root.right)root.left,root.right right,leftreturn root复杂度分析 时间复杂度&#xff1a;O(N…

HTML 学习笔记(十一)表单

一、分块 1.单行文本框控件–文本框和密码框 文本框控件通过单标签input实现&#xff0c;其具有必要属性type来控制输入控件的类型(默认为text即文本信息)&#xff0c;密码框的type为password(口令)。   表单的动作属性定义了目的文件的文件名。由动作属性定义的这个文件通常…

Docker 安装部署MySQL教程

前言 Docker安装MySQL镜像以及启动容器&#xff0c;大致都是三步&#xff1a;查询镜像–>拉取镜像–>启动容器 1、查询镜像 docker search mysql2、拉取镜像 拉取镜像时选择stars值较高的 docker pull mysql:5.7 #这里指定拉取对应的版本Mysql5.7&#xff0c;没有指…

ArcGIS学习(十六)基于交通网络的城市情景分析

ArcGIS学习(十六)基于交通网络的城市情景分析 本任务给大家带来一个非常重要的内容一一基于交通网络的城市情景分析。基于交通网络模拟交通出行并进行相关分析是ArcGIS里面一种常用的分析方法,大家一定要掌握!本任务包括三个关卡: 交通网络模型构建基于交通网络模型的基本…

Gitlab CICD 下载artifacts文件并用allure打开,或bat文件打开

allure命令行打开aritfacts报告 首先下载allure.zip&#xff0c;并解压 配置环境变量 使用命令行打开allure文件夹 allure open 2024-03-11-14-54-40 2024-03-11-14-54-40 包含index.html Bat文件打开artifacts There are 2 html reports in the download artifacts.zip S…

EXCEL根据某列的数字N,增加N-1行相同的数据

因为工作需要&#xff0c;需要将表格数据拆分&#xff0c;类似于相同的订单有6笔&#xff0c;数据表中就是一行数据但是订单数为6&#xff0c;但是需要将其拆分成相同6笔的订单数为1的数据行。 需要使用VBA代码&#xff0c;具体做法如下&#xff1a; Dim i As Long, j As Long…