Visual Servoing Platform  version 3.0.0
vpFFMPEG.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Class that manages the FFMPEG library.
32  *
33  * Authors:
34  * Nicolas Melchior
35  * Fabien Spindler
36  *
37  *****************************************************************************/
38 
44 #include <stdio.h>
45 
46 #include <visp3/core/vpConfig.h>
47 #include <visp3/core/vpDebug.h>
48 #include <visp3/io/vpFFMPEG.h>
49 #include <visp3/core/vpImageConvert.h>
50 
51 #ifdef VISP_HAVE_FFMPEG
52 
53 extern "C"
54 {
55 //#include <libavcodec/avcodec.h>
56 #include <libavformat/avformat.h>
57 #include <libswscale/swscale.h>
58 }
59 
64  : width(-1), height(-1), frameNumber(0), pFormatCtx(NULL), pCodecCtx(NULL),
65  pCodec(NULL), pFrame(NULL), pFrameRGB(NULL), pFrameGRAY(NULL), packet(NULL),
66  img_convert_ctx(NULL), videoStream(0), numBytes(0), buffer(NULL), index(),
67  streamWasOpen(false), streamWasInitialized(false), color_type(COLORED),
68  f(NULL), outbuf(NULL), picture_buf(NULL), outbuf_size(0), out_size(0),
69  bit_rate(500000), encoderWasOpened(false),
70  framerate_stream(-1), framerate_encoder(25)
71 {
72  packet = new AVPacket;
73 }
74 
79 {
80  closeStream();
81  delete packet;
82 }
83 
95 bool vpFFMPEG::openStream(const char *filename, vpFFMPEGColorType colortype)
96 {
97  this->color_type = colortype;
98 
99  av_register_all();
100 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53,0,0) // libavformat 52.84.0
101  if (av_open_input_file (&pFormatCtx, filename, NULL, 0, NULL) != 0)
102 #else
103  if (avformat_open_input (&pFormatCtx, filename, NULL, NULL) != 0) // libavformat 53.4.0
104 #endif
105  {
106  vpTRACE("Couldn't open file ");
107  return false;
108  }
109 
110 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53,21,0) // libavformat 53.21.0
111  if (av_find_stream_info (pFormatCtx) < 0)
112 #else
113  if (avformat_find_stream_info (pFormatCtx, NULL) < 0)
114 #endif
115  return false;
116 
117  videoStream = 0;
118  bool found_codec = false;
119 
120  /*
121  * Detect streams types
122  */
123  for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++)
124  {
125 #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51,0,0)
126  if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) // avutil 50.33.0
127 #else
128  if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) // avutil 51.9.1
129 #endif
130  {
131  videoStream = i;
132  //std::cout << "rate: " << pFormatCtx->streams[i]->r_frame_rate.num << " " << pFormatCtx->streams[i]->r_frame_rate.den << std::endl;
133 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(55,12,0)
134  framerate_stream = pFormatCtx->streams[i]->r_frame_rate.num;
135  framerate_stream /= pFormatCtx->streams[i]->r_frame_rate.den;
136 #else
137  framerate_stream = pFormatCtx->streams[i]->avg_frame_rate.num;
138  framerate_stream /= pFormatCtx->streams[i]->avg_frame_rate.den;
139 #endif
140  found_codec= true;
141  break;
142  }
143  }
144 
145  if (found_codec)
146  {
147  pCodecCtx = pFormatCtx->streams[videoStream]->codec;
148  pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
149 
150  if (pCodec == NULL)
151  {
152  vpTRACE("unsuported codec");
153  return false; // Codec not found
154  }
155 
156 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53,35,0) // libavcodec 53.35.0
157  if (avcodec_open (pCodecCtx, pCodec) < 0)
158 #else
159  if (avcodec_open2 (pCodecCtx, pCodec, NULL) < 0)
160 #endif
161  {
162  vpTRACE("Could not open codec");
163  return false; // Could not open codec
164  }
165 
166 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,34,0)
167  pFrame = avcodec_alloc_frame();
168 #else
169  pFrame = av_frame_alloc(); // libavcodec 55.34.1
170 #endif
171 
172  if (color_type == vpFFMPEG::COLORED)
173  {
174 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,34,0)
175  pFrameRGB=avcodec_alloc_frame();
176 #else
177  pFrameRGB=av_frame_alloc(); // libavcodec 55.34.1
178 #endif
179 
180  if (pFrameRGB == NULL)
181  return false;
182 
183  numBytes = avpicture_get_size (PIX_FMT_RGB24,pCodecCtx->width,pCodecCtx->height);
184  }
185 
186  else if (color_type == vpFFMPEG::GRAY_SCALED)
187  {
188 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,34,0)
189  pFrameGRAY=avcodec_alloc_frame();
190 #else
191  pFrameGRAY=av_frame_alloc(); // libavcodec 55.34.1
192 #endif
193 
194  if (pFrameGRAY == NULL)
195  return false;
196 
197  numBytes = avpicture_get_size (PIX_FMT_GRAY8,pCodecCtx->width,pCodecCtx->height);
198  }
199 
200  /*
201  * Determine required buffer size and allocate buffer
202  */
203  width = pCodecCtx->width ;
204  height = pCodecCtx->height ;
205  buffer = (uint8_t *) malloc ((unsigned int)(sizeof (uint8_t)) * (unsigned int)numBytes);
206  }
207  else
208  {
209  vpTRACE("Didn't find a video stream");
210  return false;
211  }
212 
213  if (color_type == vpFFMPEG::COLORED)
214  avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
215 
216  else if (color_type == vpFFMPEG::GRAY_SCALED)
217  avpicture_fill((AVPicture *)pFrameGRAY, buffer, PIX_FMT_GRAY8, pCodecCtx->width, pCodecCtx->height);
218 
219  streamWasOpen = true;
220 
221  return true;
222 }
223 
232 {
233  if (color_type == vpFFMPEG::COLORED)
234  img_convert_ctx= sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width,pCodecCtx->height,PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
235 
236  else if (color_type == vpFFMPEG::GRAY_SCALED)
237  img_convert_ctx= sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width,pCodecCtx->height,PIX_FMT_GRAY8, SWS_BICUBIC, NULL, NULL, NULL);
238 
239  int ret = av_seek_frame(pFormatCtx, (int)videoStream, 0, AVSEEK_FLAG_ANY) ;
240  if (ret < 0 )
241  {
242  vpTRACE("Error rewinding stream for full indexing") ;
243  return false ;
244  }
245  avcodec_flush_buffers(pCodecCtx) ;
246 
247  int frame_no = 0 ;
248  int frameFinished ;
249 
250  av_init_packet(packet);
251  while (av_read_frame (pFormatCtx, packet) >= 0)
252  {
253  if (packet->stream_index == (int)videoStream)
254  {
255 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52,72,2)
256  ret = avcodec_decode_video(pCodecCtx, pFrame,
257  &frameFinished, packet->data, packet->size);
258 #else
259  ret = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, packet); // libavcodec >= 52.72.2 (0.6)
260 #endif
261  if (frameFinished)
262  {
263  if (ret < 0 )
264  {
265  vpTRACE("Unable to decode video picture");
266  }
267  index.push_back(packet->dts);
268  frame_no++ ;
269  }
270  }
271  }
272 
273  frameNumber = index.size();
274  av_free_packet(packet);
275 
276  streamWasInitialized = true;
277 
278  return true;
279 }
280 
281 
290 bool vpFFMPEG::getFrame(vpImage<vpRGBa> &I, unsigned int frame)
291 {
292 
293  if (frame < frameNumber && streamWasInitialized== true)
294  {
295  int64_t targetPts = index[frame];
296  av_seek_frame(pFormatCtx, (int)videoStream,targetPts, AVSEEK_FLAG_ANY);
297  }
298  else
299  {
300  vpTRACE("Couldn't get a frame");
301  return false;
302  }
303 
304  avcodec_flush_buffers(pCodecCtx) ;
305 
306  int frameFinished ;
307 
308  av_init_packet(packet);
309  while (av_read_frame (pFormatCtx, packet) >= 0)
310  {
311  if (packet->stream_index == (int)videoStream)
312  {
313 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52,72,2)
314  avcodec_decode_video(pCodecCtx, pFrame,
315  &frameFinished, packet->data, packet->size);
316 #else
317  avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, packet); // libavcodec >= 52.72.2 (0.6)
318 #endif
319  if (frameFinished)
320  {
321  if (color_type == vpFFMPEG::COLORED)
322  sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
323  else if (color_type == vpFFMPEG::GRAY_SCALED)
324  sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameGRAY->data, pFrameGRAY->linesize);
325 
326  copyBitmap(I);
327  break;
328  }
329  }
330  }
331 
332  av_free_packet(packet);
333  return true;
334 }
335 
336 
345 {
346  int frameFinished ;
347 
348  if (streamWasInitialized == false)
349  {
350  vpTRACE("Couldn't get a frame. The parameters have to be initialized before ");
351  return false;
352  }
353 
354  av_init_packet(packet);
355  while (av_read_frame (pFormatCtx, packet) >= 0)
356  {
357  if (packet->stream_index == (int)videoStream)
358  {
359 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52,72,2)
360  avcodec_decode_video(pCodecCtx, pFrame,
361  &frameFinished, packet->data, packet->size);
362 #else
363  avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, packet); // libavcodec >= 52.72.2 (0.6)
364 #endif
365  if (frameFinished)
366  {
367  if (color_type == vpFFMPEG::COLORED)
368  sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
369  else if (color_type == vpFFMPEG::GRAY_SCALED)
370  sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameGRAY->data, pFrameGRAY->linesize);
371 
372  copyBitmap(I);
373  break;
374  }
375  }
376  }
377  av_free_packet(packet);
378  return true;
379 }
380 
389 bool vpFFMPEG::getFrame(vpImage<unsigned char> &I, unsigned int frame)
390 {
391 
392  if (frame < frameNumber && streamWasInitialized== true)
393  {
394  int64_t targetPts = index[frame];
395  av_seek_frame(pFormatCtx,(int)videoStream,targetPts, AVSEEK_FLAG_ANY);
396  }
397  else
398  {
399  vpTRACE("Couldn't get a frame");
400  return false;
401  }
402 
403  avcodec_flush_buffers(pCodecCtx) ;
404 
405  int frameFinished ;
406 
407  av_init_packet(packet);
408  while (av_read_frame (pFormatCtx, packet) >= 0)
409  {
410  if (packet->stream_index == (int)videoStream)
411  {
412 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52,72,2)
413  avcodec_decode_video(pCodecCtx, pFrame,
414  &frameFinished, packet->data, packet->size);
415 #else
416  avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, packet); // libavcodec >= 52.72.2 (0.6)
417 #endif
418  if (frameFinished)
419  {
420  if (color_type == vpFFMPEG::COLORED)
421  sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
422  else if (color_type == vpFFMPEG::GRAY_SCALED)
423  sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameGRAY->data, pFrameGRAY->linesize);
424 
425  copyBitmap(I);
426  break;
427  }
428  }
429  }
430 
431  av_free_packet(packet);
432  return true;
433 }
434 
435 
444 {
445  int frameFinished ;
446 
447  if (streamWasInitialized == false)
448  {
449  vpTRACE("Couldn't get a frame. The parameters have to be initialized before ");
450  return false;
451  }
452 
453  av_init_packet(packet);
454  while (av_read_frame (pFormatCtx, packet) >= 0)
455  {
456  if (packet->stream_index == (int)videoStream)
457  {
458 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52,72,2)
459  avcodec_decode_video(pCodecCtx, pFrame,
460  &frameFinished, packet->data, packet->size);
461 #else
462  avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, packet); // libavcodec >= 52.72.2 (0.6)
463 #endif
464  if (frameFinished)
465  {
466  if (color_type == vpFFMPEG::COLORED)
467  sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
468  else if (color_type == vpFFMPEG::GRAY_SCALED)
469  sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameGRAY->data, pFrameGRAY->linesize);
470 
471  copyBitmap(I);
472  break;
473  }
474  }
475  }
476  av_free_packet(packet);
477  return true;
478 }
479 
480 
489 void vpFFMPEG::copyBitmap(vpImage<vpRGBa> &I)
490 {
491  if(height < 0 || width < 0){
492  throw vpException(vpException::dimensionError, "width or height negative.");
493  }
494  I.resize((unsigned int)height, (unsigned int)width);
495 
496  unsigned char* line;
497  unsigned char* beginOutput = (unsigned char*)I.bitmap;
498  unsigned char* output = NULL;
499 
500  if (color_type == COLORED)
501  {
502  unsigned char* input = (unsigned char*)pFrameRGB->data[0];
503  int widthStep = pFrameRGB->linesize[0];
504  for(int i=0 ; i < height ; i++)
505  {
506  line = input;
507  output = beginOutput + 4 * width * i;
508  for(int j=0 ; j < width ; j++)
509  {
510  *(output++) = *(line);
511  *(output++) = *(line+1);
512  *(output++) = *(line+2);
513  *(output++) = 0;
514 
515  line+=3;
516  }
517  //go to the next line
518  input+=widthStep;
519  }
520  }
521 
522  else if (color_type == GRAY_SCALED)
523  {
524  unsigned char* input = (unsigned char*)pFrameGRAY->data[0];
525  int widthStep = pFrameGRAY->linesize[0];
526  for(int i=0 ; i < height ; i++)
527  {
528  line = input;
529  output = beginOutput + 4 * width * i;
530  for(int j=0 ; j < width ; j++)
531  {
532  *output++ = *(line);
533  *output++ = *(line);
534  *output++ = *(line);
535  *output++ = *(line);;
536 
537  line++;
538  }
539  //go to the next line
540  input+=widthStep;
541  }
542  }
543 }
544 
553 void vpFFMPEG::copyBitmap(vpImage<unsigned char> &I)
554 {
555  if(height < 0 || width < 0){
556  throw vpException(vpException::dimensionError, "width or height negative.");
557  }
558  I.resize((unsigned int)height, (unsigned int)width);
559 
560  unsigned char* line;
561  unsigned char* beginOutput = (unsigned char*)I.bitmap;
562  unsigned char* output = NULL;
563 
564  if (color_type == GRAY_SCALED)
565  {
566  unsigned char* input = (unsigned char*)pFrameGRAY->data[0];
567  int widthStep = pFrameGRAY->linesize[0];
568  for(int i=0 ; i < height ; i++)
569  {
570  line = input;
571  output = beginOutput + width * i;
572  for(int j=0 ; j < width ; j++)
573  {
574  *(output++) = *(line);
575 
576  line++;
577  }
578  //go to the next line
579  input+=widthStep;
580  }
581  }
582 
583  if (color_type == COLORED)
584  {
585  unsigned char* input = (unsigned char*)pFrameRGB->data[0];
586  int widthStep = pFrameRGB->linesize[0];
587  for (int i = 0 ; i < height ; i++)
588  {
589  vpImageConvert::RGBToGrey(input + i*widthStep, beginOutput + i*width, (unsigned int)width, 1, false);
590  }
591  }
592 }
593 
598 {
599  if (streamWasOpen)
600  {
601  if (buffer != NULL) {
602  free(buffer);
603  buffer = NULL;
604  }
605 
606  if (color_type == vpFFMPEG::COLORED)
607  av_free(pFrameRGB);
608 
609  else if (color_type == vpFFMPEG::GRAY_SCALED)
610  av_free(pFrameGRAY);
611 
612  // Free the YUV frame
613  av_free(pFrame);
614 
615  // Close the codec
616  if (pCodecCtx) avcodec_close(pCodecCtx);
617 
618  // Close the video file
619 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53,17,0) // libavformat 53.17.0
620  av_close_input_file(pFormatCtx);
621 #else
622  avformat_close_input(&pFormatCtx);
623 #endif
624  }
625  streamWasOpen = false;
626 
627  if (encoderWasOpened)
628  {
629  if(f!=NULL) endWrite();
630 
631  if(buffer!=NULL) delete[] buffer;
632 
633  if(outbuf != NULL) delete[] outbuf;
634 
635  if(picture_buf != NULL) delete[] picture_buf;
636 
637  av_free(pFrameRGB);
638  av_free(pFrame);
639  if (pCodecCtx) avcodec_close(pCodecCtx);
640  }
641 
642  encoderWasOpened = false;
643 
644  if(streamWasInitialized || encoderWasOpened){
645  sws_freeContext (img_convert_ctx);
646  }
647  streamWasInitialized = false;
648 }
649 
665 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,51,110) // libavcodec 54.51.100
666 bool vpFFMPEG::openEncoder(const char *filename, unsigned int w, unsigned int h, CodecID codec)
667 #else
668 bool vpFFMPEG::openEncoder(const char *filename, unsigned int w, unsigned int h, AVCodecID codec)
669 #endif
670 {
671  av_register_all();
672 
673  /* find the mpeg1 video encoder */
674  pCodec = avcodec_find_encoder(codec);
675  if (pCodec == NULL) {
676  fprintf(stderr, "codec not found\n");
677  return false;
678  }
679 
680 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53,5,0) // libavcodec 53.5.0
681  pCodecCtx = avcodec_alloc_context();
682 #else
683  pCodecCtx = avcodec_alloc_context3(NULL);
684 #endif
685 
686 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,34,0)
687  pFrame = avcodec_alloc_frame();
688  pFrameRGB = avcodec_alloc_frame();
689 #else
690  pFrame = av_frame_alloc(); // libavcodec 55.34.1
691  pFrameRGB = av_frame_alloc(); // libavcodec 55.34.1
692 #endif
693 
694  /* put sample parameters */
695  pCodecCtx->bit_rate = (int)bit_rate;
696  /* resolution must be a multiple of two */
697  pCodecCtx->width = (int)w;
698  pCodecCtx->height = (int)h;
699  this->width = (int)w;
700  this->height = (int)h;
701  /* frames per second */
702  pCodecCtx->time_base.num = 1;
703  pCodecCtx->time_base.den = framerate_encoder;
704  pCodecCtx->gop_size = 10; /* emit one intra frame every ten frames */
705  pCodecCtx->max_b_frames=1;
706  pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
707 
708  /* open it */
709 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53,35,0) // libavcodec 53.35.0
710  if (avcodec_open (pCodecCtx, pCodec) < 0) {
711 #else
712  if (avcodec_open2 (pCodecCtx, pCodec, NULL) < 0) {
713 #endif
714  fprintf(stderr, "could not open codec\n");
715  return false;
716  }
717 
718  /* the codec gives us the frame size, in samples */
719 
720  f = fopen(filename, "wb");
721  if (!f) {
722  fprintf(stderr, "could not open %s\n", filename);
723  return false;
724  }
725 
726  outbuf_size = 100000;
727  outbuf = new uint8_t[outbuf_size];
728 
729  numBytes = avpicture_get_size (PIX_FMT_YUV420P,pCodecCtx->width,pCodecCtx->height);
730  picture_buf = new uint8_t[numBytes];
731  avpicture_fill((AVPicture *)pFrame, picture_buf, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
732 
733  numBytes = avpicture_get_size (PIX_FMT_RGB24,pCodecCtx->width,pCodecCtx->height);
734  buffer = new uint8_t[numBytes];
735  avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
736 
737  img_convert_ctx= sws_getContext(pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, pCodecCtx->width,pCodecCtx->height,PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
738 
739  encoderWasOpened = true;
740 
741  return true;
742 }
743 
744 
753 {
754  if (encoderWasOpened == false)
755  {
756  vpTRACE("Couldn't save a frame. The parameters have to be initialized before ");
757  return false;
758  }
759 
760  writeBitmap(I);
761  sws_scale(img_convert_ctx, pFrameRGB->data, pFrameRGB->linesize, 0, pCodecCtx->height, pFrame->data, pFrame->linesize);
762 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,2,100) // libavcodec 54.2.100
763  out_size = avcodec_encode_video(pCodecCtx, outbuf, outbuf_size, pFrame);
764  fwrite(outbuf, 1, (size_t)out_size, f);
765 #else
766  AVPacket pkt;
767  av_init_packet(&pkt);
768  pkt.data = NULL; // packet data will be allocated by the encoder
769  pkt.size = 0;
770 
771  int got_output;
772  int ret = avcodec_encode_video2(pCodecCtx, &pkt, pFrame, &got_output);
773  if (ret < 0) {
774  std::cerr << "Error encoding frame in " << __FILE__ << " " << __LINE__ << " " << __FUNCTION__ << std::endl;
775  return false;
776  }
777  if (got_output) {
778  fwrite(pkt.data, 1, pkt.size, f);
779  av_free_packet(&pkt);
780  }
781 #endif
782  fflush(stdout);
783  return true;
784 }
785 
786 
795 {
796  if (encoderWasOpened == false)
797  {
798  vpTRACE("Couldn't save a frame. The parameters have to be initialized before ");
799  return false;
800  }
801 
802  writeBitmap(I);
803  sws_scale(img_convert_ctx, pFrameRGB->data, pFrameRGB->linesize, 0, pCodecCtx->height, pFrame->data, pFrame->linesize);
804 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,2,100) // libavcodec 54.2.100
805  out_size = avcodec_encode_video(pCodecCtx, outbuf, outbuf_size, pFrame);
806  fwrite(outbuf, 1, (size_t)out_size, f);
807 #else
808  AVPacket pkt;
809  av_init_packet(&pkt);
810  pkt.data = NULL; // packet data will be allocated by the encoder
811  pkt.size = 0;
812 
813  int got_output;
814  int ret = avcodec_encode_video2(pCodecCtx, &pkt, pFrame, &got_output);
815  if (ret < 0) {
816  std::cerr << "Error encoding frame in " << __FILE__ << " " << __LINE__ << " " << __FUNCTION__ << std::endl;
817  return false;
818  }
819  if (got_output) {
820  fwrite(pkt.data, 1, pkt.size, f);
821  av_free_packet(&pkt);
822  }
823 #endif
824 
825  fflush(stdout);
826  return true;
827 }
828 
835 {
836  if (encoderWasOpened == false)
837  {
838  vpTRACE("Couldn't save a frame. The parameters have to be initialized before ");
839  return false;
840  }
841 
842  int ret = 1;
843  while (ret != 0)
844  {
845 
846 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,2,100) // libavcodec 54.2.100
847  ret = avcodec_encode_video(pCodecCtx, outbuf, outbuf_size, NULL);
848  fwrite(outbuf, 1, (size_t)out_size, f);
849 #else
850  AVPacket pkt;
851  av_init_packet(&pkt);
852  pkt.data = NULL; // packet data will be allocated by the encoder
853  pkt.size = 0;
854  int got_output;
855  ret = avcodec_encode_video2(pCodecCtx, &pkt, NULL, &got_output);
856  if (ret < 0) {
857  std::cerr << "Error encoding frame in " << __FILE__ << " " << __LINE__ << " " << __FUNCTION__ << std::endl;
858  return false;
859  }
860  if (got_output) {
861  fwrite(pkt.data, 1, pkt.size, f);
862  av_free_packet(&pkt);
863  }
864 #endif
865  }
866 
867  /*The end of a mpeg file*/
868  outbuf[0] = 0x00;
869  outbuf[1] = 0x00;
870  outbuf[2] = 0x01;
871  outbuf[3] = 0xb7;
872  fwrite(outbuf, 1, 4, f);
873  fclose(f);
874  f = NULL;
875  return true;
876 }
877 
881 void vpFFMPEG::writeBitmap(vpImage<vpRGBa> &I)
882 {
883  unsigned char* beginInput = (unsigned char*)I.bitmap;
884  unsigned char* input = NULL;
885  unsigned char* output = NULL;
886  unsigned char* beginOutput = (unsigned char*)pFrameRGB->data[0];
887  int widthStep = pFrameRGB->linesize[0];
888 
889  for(int i=0 ; i < height ; i++)
890  {
891  input = beginInput + 4 * i * width;
892  output = beginOutput + i * widthStep;
893  for(int j=0 ; j < width ; j++)
894  {
895  *(output++) = *(input);
896  *(output++) = *(input+1);
897  *(output++) = *(input+2);
898 
899  input+=4;
900  }
901  }
902 }
903 
904 
908 void vpFFMPEG::writeBitmap(vpImage<unsigned char> &I)
909 {
910  unsigned char* beginInput = (unsigned char*)I.bitmap;
911  unsigned char* input = NULL;
912  unsigned char* output = NULL;
913  unsigned char* beginOutput = (unsigned char*)pFrameRGB->data[0];
914  int widthStep = pFrameRGB->linesize[0];
915 
916  for(int i=0 ; i < height ; i++)
917  {
918  input = beginInput + i * width;
919  output = beginOutput + i * widthStep;
920  for(int j=0 ; j < width ; j++)
921  {
922  *(output++) = *(input);
923  *(output++) = *(input);
924  *(output++) = *(input);
925 
926  input++;
927  }
928  }
929 }
930 
931 #elif !defined(VISP_BUILD_SHARED_LIBS)
932 // Work arround to avoid warning: libvisp_core.a(vpFFMPEG.cpp.o) has no symbols
933 void dummy_vpFFMPEG() {};
934 #endif
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int size)
Type * bitmap
points toward the bitmap
Definition: vpImage.h:116
bool saveFrame(vpImage< vpRGBa > &I)
Definition: vpFFMPEG.cpp:752
bool getFrame(vpImage< vpRGBa > &I, unsigned int frameNumber)
Definition: vpFFMPEG.cpp:290
error that can be emited by ViSP classes.
Definition: vpException.h:73
vpFFMPEG()
Definition: vpFFMPEG.cpp:63
#define vpTRACE
Definition: vpDebug.h:414
bool openStream(const char *filename, vpFFMPEGColorType color_type)
Definition: vpFFMPEG.cpp:95
void resize(const unsigned int h, const unsigned int w)
set the size of the image without initializing it.
Definition: vpImage.h:616
~vpFFMPEG()
Definition: vpFFMPEG.cpp:78
vpFFMPEGColorType
Definition: vpFFMPEG.h:148
void closeStream()
Definition: vpFFMPEG.cpp:597
bool acquire(vpImage< vpRGBa > &I)
Definition: vpFFMPEG.cpp:344
bool initStream()
Definition: vpFFMPEG.cpp:231
bool endWrite()
Definition: vpFFMPEG.cpp:834
bool openEncoder(const char *filename, unsigned int width, unsigned int height, AVCodecID codec=AV_CODEC_ID_MPEG1VIDEO)
Definition: vpFFMPEG.cpp:668