目录
- 源码下载
- 编译和安装
- API简单使用
- 源代码
- 编译
- 运行
- 工具的简单使用
- 学习论坛
源码下载
地址: https://github.com/FFmpeg/FFmpeg
git clone https://github.com/FFmpeg/FFmpeg.git
编译和安装
- 因为使用在板端编译,因此没有使用交叉编译链的部分。
- 将如下内容复制到
build.sh
, 执行sh build.sh
./configure \--prefix="$PWD/install" \--enable-shared \--target-os=linux \--arch=aarch64 \--enable-gpl \--extra-libs=-ldl \--extra-cflags="-fPIC" \--extra-ldflags=-Wl,-Bsymbolic \--extra-libs="-lpthread -lm"
- 如果没有报错,执行make -j4;make install
- 以上版本工具有
ffmpeg
和ffprobe
- 接口在install目录下的include和lib
- 以上版本工具有
API简单使用
源代码
xxxxxxxxxxxxxxxxxxxx.hpp
#ifndef FILE_2_FRAME_H__
#define FILE_2_FRAME_H__#include <thread>
#include <string>
extern "C" {#include <libavformat/avformat.h>
}class CFile2Frame {
public:static constexpr char *RED_START = (char*)"\033[1;31m";static constexpr char *GREEN_START = (char*)"\033[1;32m";static constexpr char *COLOR_END = (char*)"\033[0m";typedef void (*func_data)(char*, int, void*pUser);public:CFile2Frame(const std::string &filePath);~CFile2Frame();int start();int videoFormatConversion();void file2FrameExecLoop(void);void loop();static unsigned frameNo_;
private:bool isExit_;std::thread *pff_;func_data frameCb_;std::string strfileNamePath_;//ffmpegAVFormatContext *ic_{nullptr};AVDictionary *opts_{nullptr};AVPacket *pkt;bool initSucc ; /*初始化成功完成标志, 读帧准备前的初始化*/int VideoStreamIndex_;};#endif
xxxxxxxxxxxxxxxxxxxxx.cpp
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>#include <file2Frame.h>unsigned CFile2Frame::frameNo_=0U;static void frameCallback(char *pdata, int size, void *pUser)
{if(pUser){// *this}printf("fn:%06d - frame_size:%d\n", ++CFile2Frame::frameNo_, size);}static double r2d(AVRational r)
{return r.den == 0 ? 0 : r.num / r.den;
}CFile2Frame::CFile2Frame(const std::string &filePath):frameCb_(frameCallback),pff_(nullptr), isExit_(false),strfileNamePath_(filePath),initSucc(false), VideoStreamIndex_(0){pff_ = new std::thread(&CFile2Frame::file2FrameExecLoop,this);if(!pff_){printf( "create file2FrameExecLoop failure!!!" "\n");}}CFile2Frame::~CFile2Frame()
{isExit_ = true;if(pkt){av_packet_free(&pkt);if(nullptr != ic_){avformat_close_input(&ic_); ic_ = nullptr;}}
}void CFile2Frame::file2FrameExecLoop(void){int ret = 0;frameCb_ = frameCallback;pkt = av_packet_alloc();printf( "开始从%s文件中分离帧数据****" "\n", strfileNamePath_.c_str());while(!isExit_){if(!ic_ || !initSucc){goto C;}ret = av_read_frame(ic_, pkt);if(0 != ret){std::cout << RED_START << "Read Frame End!" << COLOR_END << std::endl;;frameNo_ = 0;getchar();int ms = 3000;long long pos = ms / 1000.0 * r2d(ic_->streams[pkt->stream_index]->time_base);av_seek_frame(ic_, VideoStreamIndex_, pos, AVSEEK_FLAG_BACKWARD |AVSEEK_FLAG_FRAME);continue;}static int frameNo = 0;// if(pkt->stream_index == VideoStreamIndex_ ){printf("[No.%06d]size:%d\n", ++frameNo, pkt->size);};if(pkt->size){frameCb_( (char *)pkt->data, pkt->size, nullptr);}C:usleep(50*1000);av_packet_unref(pkt); //引用计数减1,, 为0时释放空间}}//build {g++ file2Frame.cpp -I include -I . -L ./lib -lavcodec -lavdevice -lavfilter -lavutil -lpostproc -lswscale -lavformat -lswresample -lpthread}
int CFile2Frame::start()
{av_dict_set(&opts_, "rtsp_transport", "tcp", 0);av_dict_set(&opts_, "max_delay", "500", 0);int ret = avformat_open_input(&ic_, strfileNamePath_.c_str(), nullptr, &opts_);if(0 != ret){char buf[1024]{0};av_strerror(ret, buf, sizeof(buf)-1);std::cout << "file open failed: " << buf << std::endl;return -1;}avformat_find_stream_info(ic_, nullptr);int nTime = ic_->duration / AV_TIME_BASE;std::cout << "total time : " << nTime << std::endl;av_dump_format(ic_, 0, nullptr, 0);for(unsigned int i = 0; i < ic_->nb_streams;++i){AVStream *stream = ic_->streams[i];//videoif(stream->codecpar->codec_type == AVMediaType::AVMEDIA_TYPE_VIDEO){VideoStreamIndex_ = i;printf("[No.%d] {codecid:%d, w:%d,h:%d, format:%d}\n", i, stream->codecpar->codec_id,stream->codecpar->width, stream->codecpar->height, stream->codecpar->format);printf("fps:%d, size:%d\n", stream->avg_frame_rate, stream->codecpar->frame_size);printf("\n");}}VideoStreamIndex_ = av_find_best_stream(ic_, AVMediaType::AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0); initSucc = true;
}void CFile2Frame::loop()
{while(!isExit_){usleep(100*1000);}
}
int main(int argc, char *argv[])
{auto pInv = std::make_shared<CFile2Frame>("./blue.mp4");if(pInv){pInv->start();}pInv->loop();return 0;
}
编译
g++ file2Frame.cpp -I. -I include -L lib -lavcodec -lavdevice -lavfilter -lavformat -lavutil -lpostproc -lswresample -lswscale -lpthread
运行
开始从./blue.mp4文件中分离帧数据****
total time : 136
Input #0, mpeg, from '(null)':Duration: 00:02:16.76, start: 575.453000, bitrate: 3726 kb/sStream #0:0[0x1e0]: Video: h264 (Main), yuv420p(progressive), 1920x1080, 90k tbr, 90k tbn
[No.0] {codecid:27, w:1920,h:1080, format:0}
fps:0, size:0fn:000001 - frame_size:82093
fn:000002 - frame_size:22834
fn:000003 - frame_size:20793
fn:000004 - frame_size:19749
fn:000005 - frame_size:22469
fn:000006 - frame_size:18618
fn:000007 - frame_size:14481
fn:000008 - frame_size:18327
fn:000009 - frame_size:17599
fn:000010 - frame_size:17848
fn:000011 - frame_size:17835
fn:000012 - frame_size:18050
fn:000013 - frame_size:17740
fn:000014 - frame_size:17351
fn:000015 - frame_size:17392
fn:000016 - frame_size:17268
fn:000017 - frame_size:16904
fn:000018 - frame_size:16813
fn:000019 - frame_size:20473
fn:000020 - frame_size:17199
fn:000021 - frame_size:17412
fn:000022 - frame_size:17161
fn:000023 - frame_size:16997
fn:000024 - frame_size:16883
fn:000025 - frame_size:16717
fn:000026 - frame_size:16930
fn:000027 - frame_size:16866
fn:000028 - frame_size:16792
fn:000029 - frame_size:17012
fn:000030 - frame_size:20293
fn:000031 - frame_size:82470
fn:000032 - frame_size:22369
fn:000033 - frame_size:19886
fn:000034 - frame_size:19078
fn:000035 - frame_size:18911
fn:000036 - frame_size:18635
工具的简单使用
参数 | 说明 |
---|---|
-h | help |
-t duration | 设置处理时间,格式为hh:mm:ss |
-ss position | 设置起始时间,格式为hh:mm:ss |
-b:v bitrate | 设置视频码率 |
-b:a bitrate | 设置音频码率 |
-r fps | 设置帧率 |
-s wxh | 设置帧大小,格式为WXH |
-c:v codec | 设置视频编码器 |
-c:a codec | 设置音频编码器 |
-ar freq | 设置音频采样率 |
- MP4转MJPEG
./ffmpeg -i [你的mp4文件路径] -vf "fps=30" -q:v 9 out.mjpeg
- 截取一段视频
ffmpeg -i blue.mp4 -ss 8 -t 3 -s 1280x720 -codec copy -f flv out.flv
-ss 开始时间:set the start time offset,单位秒,-t 持续时间 -s 分辨率。截取原视频中从第8秒开始,持续时间3秒的视频。输出分辨率1280x720
- 解封装
ffmpeg -i blue.mp4 -codec copy -bsf: h264_mp4toannexb -f h264 out.264
-i blue.mp4: 是输入的MP4文件-codec copy: 从mp4中拷贝-bsf: h264_mp4toannexb: 从mp4拷贝到annexB封装-f h264: 采用h264格式out.264: 输出的文件
学习论坛
传送:https://superuser.com/questions/tagged/ffmpeg