ffmpeggrabber.cpp
来自「一个语言识别引擎」· C++ 代码 · 共 531 行 · 第 1/2 页
CPP
531 行
AVFormatContext **ppFormatCtx) {
AVFormatParameters formatParams;
AVInputFormat *iformat;
formatParams.device = strdup(config.check("v4ldevice",Value("/dev/video0")).asString().c_str());
formatParams.channel = config.check("channel",Value(0)).asInt();
formatParams.standard = strdup(config.check("standard",Value("ntsc")).asString().c_str());
formatParams.width = config.check("width",Value(640)).asInt();
formatParams.height = config.check("height",Value(480)).asInt();
formatParams.time_base.den = config.check("time_base_den",
Value(29)).asInt();
formatParams.time_base.num = config.check("time_base_num",
Value(1)).asInt();
iformat = av_find_input_format("video4linux");
return (av_open_input_file(ppFormatCtx,
"", iformat, 0, &formatParams)==0);
}
bool FfmpegGrabber::openFirewire(yarp::os::Searchable & config,
AVFormatContext **ppFormatCtx) {
AVFormatParameters formatParams;
AVInputFormat *iformat;
ConstString devname = config.check("devname",Value("/dev/dv1394")).asString();
formatParams.device = devname.c_str();
iformat = av_find_input_format("dv1394");
printf("Checking for digital video in %s\n", devname.c_str());
return av_open_input_file(ppFormatCtx,
"", iformat, 0, &formatParams)==0;
}
bool FfmpegGrabber::openFile(AVFormatContext **ppFormatCtx,
const char *fname) {
return av_open_input_file(ppFormatCtx, fname, NULL, 0, NULL)==0;
}
bool FfmpegGrabber::open(yarp::os::Searchable & config) {
ConstString fname =
config.check("source",Value("default.avi")).asString();
// Register all formats and codecs
av_register_all();
// Open video file
if (config.check("v4l")) {
needRateControl = false; // reading from live media
if (!openV4L(config,&pFormatCtx)) {
printf("Could not open Video4Linux input\n");
return false;
}
} else if (config.check("ieee1394")) {
needRateControl = false; // reading from live media
if (!openFirewire(config,&pFormatCtx)) {
printf("Could not open ieee1394 input\n");
return false;
}
} else {
needRateControl = true; // reading from recorded media
if (!openFile(&pFormatCtx,fname.c_str())) {
printf("Could not open avi file %s\n", fname.c_str());
return false; // Couldn't open file
}
}
// Retrieve stream information
if(av_find_stream_info(pFormatCtx)<0) {
printf("Could not find stream information in %s\n", fname.c_str());
return false; // Couldn't find stream information
}
// Dump information about file onto standard error
dump_format(pFormatCtx, 0, fname.c_str(), false);
YARP_ASSERT(system_resource==NULL);
system_resource = new FfmpegHelper;
YARP_ASSERT(system_resource!=NULL);
FfmpegHelper& helper = HELPER(system_resource);
DecoderState& videoDecoder = helper.videoDecoder;
DecoderState& audioDecoder = helper.audioDecoder;
// Find the first video stream
int videoStream = videoDecoder.getStream(pFormatCtx,CODEC_TYPE_VIDEO,
"video");
// Find the first audio stream
int audioStream = audioDecoder.getStream(pFormatCtx,CODEC_TYPE_AUDIO,
"audio");
if (videoStream==-1&&audioStream==-1) {
return false;
}
_hasVideo = (videoStream!=-1);
_hasAudio = (audioStream!=-1);
bool ok = true;
if (_hasVideo) {
ok = ok && videoDecoder.getCodec(pFormatCtx);
}
if (_hasAudio) {
ok = ok && audioDecoder.getCodec(pFormatCtx);
}
if (!ok) return false;
if (_hasVideo) {
ok = ok && videoDecoder.allocateImage();
}
if (_hasAudio) {
ok = ok && audioDecoder.allocateSound();
}
if (!ok) return false;
if (_hasVideo) {
m_w = videoDecoder.getWidth();
m_h = videoDecoder.getHeight();
}
if (_hasAudio) {
m_channels = audioDecoder.getChannels();
m_rate = audioDecoder.getRate();
}
printf(" video size %dx%d, audio %dHz with %d channels\n", m_w, m_h,
m_rate, m_channels);
if (!(_hasVideo||_hasAudio)) {
return false;
}
active = true;
return true;
}
bool FfmpegGrabber::close() {
if (!active) {
return false;
}
// Close the video file
if (pFormatCtx!=NULL) {
av_close_input_file(pFormatCtx);
}
if (system_resource!=NULL) {
delete &HELPER(system_resource);
system_resource = NULL;
}
active = false;
return true;
}
bool FfmpegGrabber::getImage(yarp::sig::ImageOf<yarp::sig::PixelRgb> & image) {
if (!_hasVideo) {
return false;
}
Sound sound;
return getAudioVisual(image,sound);
}
bool FfmpegGrabber::getSound(yarp::sig::Sound& sound) {
if (!_hasAudio) {
return false;
}
ImageOf<PixelRgb> image;
return getAudioVisual(image,sound);
}
bool FfmpegGrabber::getAudioVisual(yarp::sig::ImageOf<yarp::sig::PixelRgb>& image,
yarp::sig::Sound& sound) {
FfmpegHelper& helper = HELPER(system_resource);
DecoderState& videoDecoder = helper.videoDecoder;
DecoderState& audioDecoder = helper.audioDecoder;
bool tryAgain = false;
bool triedAgain = false;
do {
bool gotAudio = false;
bool gotVideo = false;
if (startTime<0.5) {
startTime = Time::now();
}
double time_target = 0;
while(av_read_frame(pFormatCtx, &packet)>=0) {
// Is this a packet from the video stream?
DBG printf("frame ");
bool done = false;
if (packet.stream_index==videoDecoder.getIndex()) {
DBG printf("video ");
done = videoDecoder.getVideo(packet);
image.resize(1,1);
if (done) {
//printf("got a video frame\n");
gotVideo = true;
}
} if (packet.stream_index==audioDecoder.getIndex()) {
DBG printf("audio ");
done = audioDecoder.getAudio(packet,sound);
if (done) {
//printf("got an audio frame\n");
gotAudio = true;
}
} else {
DBG printf("other ");
}
AVRational& time_base = pFormatCtx->streams[packet.stream_index]->time_base;
double rbase = av_q2d(time_base);
DBG printf(" time=%g ", packet.pts*rbase);
time_target = packet.pts*rbase;
av_free_packet(&packet);
DBG printf(" %d\n", done);
if ((videoDecoder.haveFrame()||!_hasVideo)&&
(gotAudio||!_hasAudio)) {
if (_hasVideo) {
videoDecoder.getVideo(image);
} else {
image.resize(0,0);
}
if (needRateControl) {
double now = Time::now()-startTime;
double delay = time_target-now;
if (delay>0) {
DBG printf("DELAY %g ", delay);
Time::delay(delay);
} else {
DBG printf("NODELAY %g ", delay);
}
}
DBG printf("IMAGE size %dx%d ", image.width(), image.height());
DBG printf("SOUND size %d\n", sound.getSamples());
if (!_hasAudio) {
sound.resize(0,0);
}
return true;
}
}
tryAgain = !triedAgain;
if (tryAgain) {
#if LIBAVFORMAT_BUILD > 4616
av_seek_frame(pFormatCtx,-1,0,AVSEEK_FLAG_BACKWARD);
#else
av_seek_frame(pFormatCtx,-1,0);
#endif
startTime = Time::now();
}
} while (tryAgain);
return false;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?