19 #define MAX_AUDIO_FRAME_SIZE 192000
62 audioBufferAt(nullptr),
69 return frameFinished!=0;
79 if (pCodecCtx!=
nullptr) {
80 avcodec_close(pCodecCtx);
82 if (audioBuffer!=
nullptr) {
83 delete [] audioBuffer;
88 if (pFrameRGB!=
nullptr) {
91 if (pFrame!=
nullptr) {
94 if (pAudio!=
nullptr) {
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);
121 pCodecCtx=pFormatCtx->streams[index]->codec;
124 pCodec = avcodec_find_decoder(pFormatCtx->streams[index]->codecpar->codec_id);
125 if(pCodec==
nullptr) {
126 yCError(FFMPEGGRABBER,
"Codec not found");
131 if (avcodec_open2(pCodecCtx, pCodec,
nullptr) < 0) {
132 yCError(FFMPEGGRABBER,
"Could not open codec");
143 pFrame=av_frame_alloc();
146 pFrameRGB=av_frame_alloc();
147 if(pFrameRGB==
nullptr) {
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];
158 avpicture_fill((AVPicture *)pFrameRGB,
buffer, AV_PIX_FMT_RGB24,
159 pCodecCtx->width, pCodecCtx->height);
166 audioBuffer =
new int16_t[audioBufferLen];
167 audioBufferAt = audioBuffer;
169 "channels %d, sample_rate %d, frame_size %d",
171 pCodecCtx->sample_rate,
172 pCodecCtx->frame_size);
178 return pCodecCtx->width;
183 return pCodecCtx->height;
189 return pCodecCtx->sample_rate;
194 return pCodecCtx->channels;
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");
213 av_frame_unref(pAudio);
215 int r = avcodec_decode_audio4(pCodecCtx, pAudio, &gotFrame, &packet);
218 ct = av_samples_get_buffer_size(
nullptr,
221 pCodecCtx->sample_fmt,
225 yCError(FFMPEGGRABBER,
"error decoding audio");
228 int num_channels = getChannels();
229 int num_rate = getRate();
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++) {
242 sound.
set(audioBuffer[idx],i,j);
254 avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished,
260 int w = pCodecCtx->width;
261 int h = pCodecCtx->height;
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,
276 ((AVPicture*)pFrameRGB)->data,
277 ((AVPicture*)pFrameRGB)->linesize);
279 yCFatal(FFMPEGGRABBER,
"Software scaling not working");
282 return frameFinished;
298 return frameFinished;
303 return frameFinished;
315 #define HELPER(x) (*((FfmpegHelper*)x))
327 AVFormatContext **ppFormatCtx,
328 AVFormatContext **ppFormatCtx2)
330 bool audio = (ppFormatCtx==
nullptr);
331 AVDictionary*& formatParams =
332 *(audio?(&formatParamsAudio):(&formatParamsVideo));
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();
478 imageSync = (sync==
"image");
480 needRateControl =
true;
482 if (config.
check(
"nodelay",
"media will play in simulated realtime unless this is present")) {
483 needRateControl =
false;
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")) {
495 needRateControl =
false;
496 if (!openV4L(config,&pFormatCtx,&pFormatCtx2)) {
497 yCError(FFMPEGGRABBER,
"Could not open Video4Linux input");
500 }
else if (config.
check(
"ieee1394",
"if present, read from firewire")) {
501 needRateControl =
false;
502 if (!openFirewire(config,&pFormatCtx)) {
503 yCError(FFMPEGGRABBER,
"Could not open ieee1394 input");
507 if (!openFile(&pFormatCtx,fname.c_str())) {
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());
521 av_dump_format(pFormatCtx, 0, m_uri.c_str(),
false);
523 if (pFormatCtx2!=
nullptr) {
525 if(avformat_find_stream_info(pFormatCtx2,
nullptr)<0) {
526 yCError(FFMPEGGRABBER,
"Could not find stream information in %s", m_uri.c_str());
531 av_dump_format(pFormatCtx2, 0, m_uri.c_str(),
false);
535 if (pFormatCtx2!=
nullptr) {
536 pAudioFormatCtx = pFormatCtx2;
538 pAudioFormatCtx = pFormatCtx;
541 yCAssert(FFMPEGGRABBER, system_resource ==
nullptr);
543 yCAssert(FFMPEGGRABBER, system_resource !=
nullptr);
551 int videoStream = videoDecoder.
getStream(pFormatCtx,
555 int audioStream = audioDecoder.
getStream(pAudioFormatCtx,
559 if (videoStream==-1&&audioStream==-1) {
563 _hasVideo = (videoStream!=-1);
564 _hasAudio = (audioStream!=-1);
568 ok = ok && videoDecoder.
getCodec(pFormatCtx);
571 ok = ok && audioDecoder.
getCodec(pAudioFormatCtx);
593 m_rate = audioDecoder.
getRate();
596 " video size %dx%d, audio %dHz with %d channels, %s sync",
601 imageSync ?
"image" :
"audio");
603 if (!(_hasVideo||_hasAudio)) {
612 if (formatParamsVideo) {
613 av_dict_free(&formatParamsVideo);
614 formatParamsVideo =
nullptr;
616 if (formatParamsAudio) {
617 av_dict_free(&formatParamsAudio);
618 formatParamsAudio =
nullptr;
626 if (pFormatCtx!=
nullptr) {
627 avformat_close_input(&pFormatCtx);
629 if (pFormatCtx2!=
nullptr) {
630 avformat_close_input(&pFormatCtx2);
632 if (system_resource!=
nullptr) {
633 delete &
HELPER(system_resource);
634 system_resource =
nullptr;
647 return getAudioVisual(image,sound);
656 return getAudioVisual(image, sound);
668 bool tryAgain =
false;
669 bool triedAgain =
false;
673 bool gotAudio =
false;
674 bool gotVideo =
false;
678 double time_target = 0;
679 while(av_read_frame(pFormatCtx, &packet)>=0) {
682 if (packet.stream_index==videoDecoder.
getIndex()) {
683 done = videoDecoder.
getVideo(packet);
686 yCTrace(FFMPEGGRABBER,
"got a video frame");
689 }
if (packet.stream_index==audioDecoder.
getIndex()) {
690 done = audioDecoder.
getAudio(packet,sound);
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;
701 av_free_packet(&packet);
702 if (((imageSync?gotVideo:videoDecoder.
haveFrame())||!_hasVideo)&&
703 ((imageSync?1:gotAudio)||!_hasAudio)) {
709 if (needRateControl) {
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)
bool openFile(AVFormatContext **ppFormatCtx, const char *fname)
bool openFirewire(yarp::os::Searchable &config, AVFormatContext **ppFormatCtx)
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
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
virtual bool getAudioVisual(yarp::sig::ImageOf< yarp::sig::PixelRgb > &image, yarp::sig::Sound &sound) override
Get an image and sound.
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.
static double nowSystem()
static void delaySystem(double seconds)
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,...)
An interface for the device drivers.
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.