我想要在C快速程序,将打开一个视频,保存每一帧作为一个PPM,并转储运动矢量。 所有我能找到的教程是从大约十年前,并呼吁取消或不存在的功能。
是否有良好的网上资源,网站,视频,或教科书是涵盖了现代的方式做这些类型的东西?
我想要在C快速程序,将打开一个视频,保存每一帧作为一个PPM,并转储运动矢量。 所有我能找到的教程是从大约十年前,并呼吁取消或不存在的功能。
是否有良好的网上资源,网站,视频,或教科书是涵盖了现代的方式做这些类型的东西?
我一直在努力的有关ffmpeg和libav了好几年,也没有发现任何像样的近期API级别的教程。 有时候,我只是潜入源弄清楚是怎么回事,以及如何使用它。 此外,读取的CLI程序(其使用底层库)源也可以是提供信息。
其实, ffmpeg的建议,你刚才读的源代码,无论是真正的OSS项目或他们的榜样。 Libav提供Doxygen文档,但没有一步一步的教程。 IMO这是典型的开源项目:源可能是好的,但文件往往缺乏。
退一步说,你可能会考虑OpenCV的 ,这是有据可查的( 书存在!),并有一个更简单的API。 最后,PPM就是这样一个简单的格式,你可能可以写一个50线功能,像素保存自己,我发现了一个运动提取程序在这里 。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <math.h>
#define __STDC_CONSTANT_MACROS
//FFMPEG LIBRARIES
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libswscale/swscale.h"
#include "libavutil/opt.h"
#include "libavutil/common.h"
#include "libavutil/channel_layout.h"
#include "libavutil/imgutils.h"
#include "libavutil/mathematics.h"
#include "libavutil/samplefmt.h"
#include "libavutil/time.h"
#include "libavformat/avformat.h"
#include "libavformat/avio.h"
#include "libavfilter/avfilter.h"
#include "libavdevice/avdevice.h"
#include "libavfilter/avfiltergraph.h"
#include "libavfilter/buffersink.h"
}
using namespace std;
void SaveMyFrame(AVFrame *sAVFrame , int swidth, int sheight, int iFrame)
{
FILE *pfile;
char szFilename[32];
int y;
sprintf(szFilename , "frame%d.ppm" , iFrame);
pfile = fopen(szFilename , "wb");
if(pfile == NULL)
{
cout<<"\n\ncould'nt open file";
return;
}
fprintf(pfile , "P6\n%d %d\n255\n" , swidth , sheight );
for( y=0; y<sheight; y++)
{
fwrite(sAVFrame->data[0]+y*sAVFrame->linesize[0] , 1 , swidth*3 , pfile );
}
fclose(pfile);
}
int CaptureScene(int VideoStreamIndx ,
AVFormatContext *bAVFormatContext ,
AVCodecContext *bAVCodecContext,
AVCodec *bAVCodec )
{
AVPacket bAVPacket;
AVFrame *bAVFrame = NULL;
bAVFrame = av_frame_alloc();
AVFrame *bAVFrameRGB = NULL;
bAVFrameRGB = av_frame_alloc();
if(bAVFrame == NULL)
{
cout<<"\n\nframe alloc failed";
}
if(bAVFrameRGB == NULL)
{
cout<<"\n\nframe alloc RGB failed";
}
int numBytes;
uint8_t *buffer = NULL;
numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24 , bAVCodecContext->width,bAVCodecContext->height, 32); // avpicture_get_size deprecated
buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
avpicture_fill((AVPicture *)bAVFrameRGB , buffer , AV_PIX_FMT_RGB24 , bAVCodecContext->width , bAVCodecContext->height);
int framefinish;
struct SwsContext *sws_ctx = NULL;
sws_ctx = sws_getContext( bAVCodecContext->width,
bAVCodecContext->height,
bAVCodecContext->pix_fmt,
bAVCodecContext->width,
bAVCodecContext->height,
AV_PIX_FMT_RGB24,
SWS_BILINEAR,
NULL,NULL,NULL);
int i =0;
while(av_read_frame(bAVFormatContext,&bAVPacket) >=0)
{
if(bAVPacket.stream_index == VideoStreamIndx)
{
avcodec_decode_video2(bAVCodecContext , bAVFrame , &framefinish , &bAVPacket);
if(framefinish)
{
// convert image from native format to RGB
sws_scale(sws_ctx , (uint8_t const* const *)bAVFrame->data ,
bAVFrame->linesize , 0, bAVCodecContext->height,
bAVFrameRGB->data , bAVFrameRGB->linesize);
// save frame to disk
if(++i <= 100)SaveMyFrame(bAVFrameRGB , bAVCodecContext->width , bAVCodecContext->height , i );
}
}
}
av_free(bAVFrame);
av_free(bAVFrameRGB);
}
int main()
{
avdevice_register_all();
avcodec_register_all();
av_register_all();
char *dev_name = "/dev/video0";
int VideoStreamIndx = -1;
AVCodecContext *pAVCodecContext = NULL;
AVCodec *pAVCodec = NULL;
AVInputFormat *inputFormat =av_find_input_format("v4l2");
AVDictionary *options = NULL;
av_dict_set(&options, "framerate", "20", 0);
AVFormatContext *pAVFormatContext = NULL;
if(avformat_open_input(&pAVFormatContext, dev_name, inputFormat, NULL) != 0)
{
cout<<"\nError : could'nt open video source\n\n";
return -1;
}
if( avformat_find_stream_info( pAVFormatContext , NULL) < 0)
{
cout<<"Error : streams not found";
return -1;
}
av_dump_format(pAVFormatContext , 0 , "/dev/video1" , 0 );
for(int i=0; i<pAVFormatContext->nb_streams ;i++ )
{
if( pAVFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) // if video stream found then get the index.
{
VideoStreamIndx = i;
break;
}
}
if((VideoStreamIndx) == -1)
{
cout<<"Error : video streams not found";
return -1;
}
pAVCodecContext = pAVFormatContext->streams[VideoStreamIndx]->codec;
pAVCodec = avcodec_find_decoder( pAVCodecContext->codec_id );
if(pAVCodec == NULL)
{
fprintf(stderr,"Unsupported codec !");
return -1;
}
int value = avcodec_open2(pAVCodecContext , pAVCodec , NULL);
if( value < 0)
{
cout<<"Error : Could not open codec";
return -1;
}
int Vwidth , Vheight , videoFPS , videoBaseTime , duration_2 ;
int sframe , length , Fheight;
/*
To fetch/display some media information programatically
*/
//int64_t duration_1 = pAVFormatContext->duration;
videoFPS = av_q2d(pAVFormatContext->streams[VideoStreamIndx]->r_frame_rate);
videoBaseTime = av_q2d(pAVFormatContext->streams[VideoStreamIndx]->time_base);
Vwidth = pAVFormatContext->streams[VideoStreamIndx]->codec->width;
Vheight = pAVFormatContext->streams[VideoStreamIndx]->codec->height;
//duration_2 = (unsigned long)pAVFormatContext->streams[VideoStreamIndx]->duration*(videoFPS*videoBaseTime);
cout<<"Video FPS :"<<videoFPS;
cout<<"\n\n width : "<<Vwidth;
cout<<"\n\n height : "<<Vheight;
cout<<"\n\n time base"<<videoBaseTime;
//cout<<"\n\nduration (1): "<<duration_1;
//cout<<"\n\nduration (2): "<<duration_2;
CaptureScene( VideoStreamIndx , pAVFormatContext , pAVCodecContext , pAVCodec );
avcodec_close(pAVCodecContext);
avformat_close_input(&pAVFormatContext);
return 0;
}
这个C ++代码将帮助您从USB(UVC)基于摄像头获取的图像.ppm格式。 它保存在.ppm格式格式。 使用V4L2 Linux和用于dshow的窗户。 代替照相机进帧,视频也可作为一个输入。 这个代码用熟ffmpeg的最新库。
libavutil 55 24100/55 24100
libavcodec的57. 43.100 / 43.100 57.
了libavformat 57. 37.100 / 37.100 57.
libavdevice 57. 0.101 / 0.101 57
libavfilter 6. 46.100 / 6. 46.100
libswscale 4. 1.100 / 1.100 4.
libswresample 2. 0.101 / 0.101 2
libpostproc 54. 0.100 / 0.100 54