地址: 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"
ffmpeg
和ffprobe
xxxxxxxxxxxxxxxxxxxx.hpp
#ifndef FILE_2_FRAME_H__
#define FILE_2_FRAME_H__
#include
#include
extern "C" {
#include
}
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_;
//ffmpeg
AVFormatContext *ic_{nullptr};
AVDictionary *opts_{nullptr};
AVPacket *pkt;
bool initSucc ; /*初始化成功完成标志, 读帧准备前的初始化*/
int VideoStreamIndex_;
};
#endif
xxxxxxxxxxxxxxxxxxxxx.cpp
#include
#include
#include
#include
#include
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];
//video
if(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("./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/s
Stream #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:0
fn: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 | 设置音频采样率 |
./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