19#define MAX_AUDIO_FRAME_SIZE 192000
99 int getStream(AVFormatContext *pFormatCtx, AVMediaType code,
const char *name)
103 for(
int i=0; i<(int)(pFormatCtx->nb_streams); i++) {
104 if(pFormatCtx->streams[i]->codecpar->codec_type==code) {
106 yCInfo(FFMPEGGRABBER,
"First %s stream is stream #%d", name, i);
110 if(videoStream==-1) {
111 yCError(FFMPEGGRABBER,
"Could not find %s stream", name);
124 pCodec = avcodec_find_decoder(pFormatCtx->streams[
index]->codecpar->codec_id);
126 yCError(FFMPEGGRABBER,
"Codec not found");
132 yCError(FFMPEGGRABBER,
"Could not open codec");
148 yCError(FFMPEGGRABBER,
"Could not allocate a frame");
153 int numBytes=avpicture_get_size(AV_PIX_FMT_RGB24,
pCodecCtx->width,
155 buffer=
new uint8_t[numBytes];
169 "channels %d, sample_rate %d, frame_size %d",
201 int bytesWritten = 0;
203 while (bytesRead<packet.size) {
205 AVPacket tmp = packet;
206 tmp.data += bytesRead;
207 tmp.size -= bytesRead;
209 if (!(
pAudio = av_frame_alloc())) {
210 yCFatal(FFMPEGGRABBER,
"out of memory");
218 ct = av_samples_get_buffer_size(
nullptr,
225 yCError(FFMPEGGRABBER,
"error decoding audio");
234 if (bytesRead==packet.size) {
235 int num_samples = bytesWritten/(
sizeof(int16_t)*num_channels);
236 sound.
resize(num_samples,num_channels);
240 for (
int i=0; i<num_samples; i++) {
241 for (
int j=0; j<num_channels; j++) {
262 static struct SwsContext *img_convert_ctx =
nullptr;
263 if (img_convert_ctx==
nullptr) {
264 img_convert_ctx = sws_getContext(w,h,
266 w, h, AV_PIX_FMT_RGB24,
270 nullptr,
nullptr,
nullptr);
272 if (img_convert_ctx!=
nullptr) {
273 sws_scale(img_convert_ctx, ((AVPicture*)
pFrame)->data,
274 ((AVPicture*)
pFrame)->linesize, 0,
279 yCFatal(FFMPEGGRABBER,
"Software scaling not working");
315#define HELPER(x) (*((FfmpegHelper*)x))
327 AVFormatContext **ppFormatCtx,
328 AVFormatContext **ppFormatCtx2)
330 bool audio = (ppFormatCtx==
nullptr);
331 AVDictionary*& formatParams =
334 AVInputFormat *iformat;
339 v = config.
check(
"v4ldevice",
340 Value(
"/dev/video0"),
343 v = config.
check(
"audio",
345 "optional audio device name");
352 av_dict_set_int(&formatParams,
354 config.
check(
"audio_rate",
356 "audio sample rate").asInt32(),
358 av_dict_set_int(&formatParams,
360 config.
check(
"channels",
362 "number of channels").asInt32(),
365 if (config.
check(
"time_base_num") && config.
check(
"time_base_den")) {
367 sprintf(buf,
"%d/%d",
368 config.
check(
"time_base_num",
370 "numerator of basic time unit").asInt32(),
371 config.
check(
"time_base_den",
373 "denominator of basic time unit").asInt32());
374 av_dict_set(&formatParams,
"framerate", buf, 0);
377 if (config.
check(
"channel")) {
378 av_dict_set_int(&formatParams,
380 config.
check(
"channel",
382 "channel identifier").asInt32(),
385 if (config.
check(
"standard")) {
386 av_dict_set(&formatParams,
388 config.
check(
"standard",
390 "pal versus ntsc").asString().c_str(),
393 av_dict_set_int(&formatParams,
395 config.
check(
"width",
397 "width of image").asInt32(),
399 av_dict_set_int(&formatParams,
401 config.
check(
"height",
403 "height of image").asInt32(),
407 std::string videoDevice = (config.
check(
"v4l1") ?
"video4linux" :
"video4linux2");
408 iformat = av_find_input_format(audio ?
"audio_device" : videoDevice.c_str());
410 int result = avformat_open_input(audio ? ppFormatCtx2 : ppFormatCtx,
415 bool ok = (result==0);
417 yCError(FFMPEGGRABBER,
"%s: ffmpeg error %d", v.
asString().c_str(), result);
421 if (ppFormatCtx!=
nullptr) {
422 if (config.
check(
"audio",
423 "optional audio device")) {
424 ok =
openV4L(config,
nullptr,ppFormatCtx2);
435 AVFormatContext **ppFormatCtx)
437 AVInputFormat *iformat;
438 std::string devname = config.
check(
"devname",
439 Value(
"/dev/dv1394"),
440 "firewire device name").asString();
441 iformat = av_find_input_format(
"dv1394");
442 yCInfo(FFMPEGGRABBER,
"Checking for digital video in %s", devname.c_str());
446 return avformat_open_input(ppFormatCtx, strdup(devname.c_str()), iformat,
nullptr) == 0;
454 return avformat_open_input(ppFormatCtx, fname,
nullptr,
nullptr) == 0;
461 config.
check(
"source",
462 Value(
"default.avi"),
463 "media file to read from").asString();
465 if (config.
check(
"loop",
"media should loop (default)")) {
469 if (config.
check(
"noloop",
"media should not loop")) {
477 "sync on image or audio (if have to choose)?").asString();
482 if (config.
check(
"nodelay",
"media will play in simulated realtime unless this is present")) {
487 "simulated realtime multiplier factor (must be <1 right now)").asFloat64();
491 avdevice_register_all();
494 if (config.
check(
"v4l",
"if present, read from video4linux") || config.
check(
"v4l1",
"if present, read from video4linux") || config.
check(
"v4l2",
"if present, read from video4linux2")) {
497 yCError(FFMPEGGRABBER,
"Could not open Video4Linux input");
500 }
else if (config.
check(
"ieee1394",
"if present, read from firewire")) {
503 yCError(FFMPEGGRABBER,
"Could not open ieee1394 input");
508 yCError(FFMPEGGRABBER,
"Could not open media file %s", fname.c_str());
515 if(avformat_find_stream_info(
pFormatCtx,
nullptr)<0) {
516 yCError(FFMPEGGRABBER,
"Could not find stream information in %s",
m_uri.c_str());
525 if(avformat_find_stream_info(
pFormatCtx2,
nullptr)<0) {
526 yCError(FFMPEGGRABBER,
"Could not find stream information in %s",
m_uri.c_str());
559 if (videoStream==-1&&audioStream==-1) {
596 " video size %dx%d, audio %dHz with %d channels, %s sync",
668 bool tryAgain =
false;
669 bool triedAgain =
false;
673 bool gotAudio =
false;
674 bool gotVideo =
false;
678 double time_target = 0;
686 yCTrace(FFMPEGGRABBER,
"got a video frame");
692 yCTrace(FFMPEGGRABBER,
"got an audio frame");
696 AVRational& time_base =
pFormatCtx->streams[
packet.stream_index]->time_base;
697 double rbase = av_q2d(time_base);
699 time_target =
packet.pts*rbase;
713 SystemClock::delaySystem(
delay);
724 tryAgain = !triedAgain;
730 av_seek_frame(
pFormatCtx,-1,0,AVSEEK_FLAG_BACKWARD);
const char * xstrdup(const char *str)
#define MAX_AUDIO_FRAME_SIZE
bool getCodec(AVFormatContext *pFormatCtx)
bool getVideo(AVPacket &packet)
bool getAudio(AVPacket &packet, Sound &sound)
bool getVideo(ImageOf< PixelRgb > &image)
int getStream(AVFormatContext *pFormatCtx, AVMediaType code, const char *name)
AVCodecContext * pCodecCtx
bool openV4L(yarp::os::Searchable &config, AVFormatContext **ppFormatCtx, AVFormatContext **ppFormatCtx2)
int m_w
Width of the images a grabber produces.
bool openFile(AVFormatContext **ppFormatCtx, const char *fname)
int m_h
Height of the images a grabber produces.
bool openFirewire(yarp::os::Searchable &config, AVFormatContext **ppFormatCtx)
AVFormatContext * pAudioFormatCtx
bool getSound(yarp::sig::Sound &sound, size_t min_number_of_samples, size_t max_number_of_samples, double max_samples_timeout_s) override
Get a sound from a device.
bool getImage(yarp::sig::ImageOf< yarp::sig::PixelRgb > &image) override
Get an image from the frame grabber.
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
AVDictionary * formatParamsAudio
AVFormatContext * pFormatCtx2
std::string m_uri
Uri of the images a grabber produces.
virtual bool getAudioVisual(yarp::sig::ImageOf< yarp::sig::PixelRgb > &image, yarp::sig::Sound &sound) override
Get an image and sound.
AVFormatContext * pFormatCtx
AVDictionary * formatParamsVideo
bool close() override
Close the DeviceDriver.
DecoderState videoDecoder
DecoderState audioDecoder
A base class for nested structures that can be searched.
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
A single value (typically within a Bottle).
virtual std::string asString() const
Get string value.
Image class with user control of representation details.
void setQuantum(size_t imgQuantum)
void setPixelCode(int imgPixelCode)
void setExternal(const void *data, size_t imgWidth, size_t imgHeight)
Use this to wrap an external image.
bool copy(const Image &alt)
Copy operator.
void resize(size_t imgWidth, size_t imgHeight)
Reallocate an image to be of a desired size, throwing away its current contents.
Class for storing sounds See Audio in YARP for additional documentation on YARP audio.
void setFrequency(int freq)
Set the frequency of the sound (i.e.
void resize(size_t samples, size_t channels=1)
Set the sound size.
void set(audio_sample value, size_t sample, size_t channel=0)
#define yCInfo(component,...)
#define yCError(component,...)
#define yCAssert(component, x)
#define yCTrace(component,...)
#define YARP_LOG_COMPONENT(name,...)
#define yCFatal(component,...)
For streams capable of holding different kinds of content, check what they actually have.
double now()
Return the current time in seconds, relative to an arbitrary starting point.
void delay(double seconds)
Wait for a certain number of seconds.
An interface to the operating system, including Port based communication.