Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpFFMPEG.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 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* beginOutput = (unsigned char*)I.bitmap;
561 
562  if (color_type == GRAY_SCALED)
563  {
564  unsigned char* input = (unsigned char*)pFrameGRAY->data[0];
565  int widthStep = pFrameGRAY->linesize[0];
566  for(int i=0 ; i < height ; i++)
567  {
568  unsigned char *line = input;
569  unsigned char *output = beginOutput + width * i;
570  for(int j=0 ; j < width ; j++)
571  {
572  *(output++) = *(line);
573 
574  line++;
575  }
576  //go to the next line
577  input+=widthStep;
578  }
579  }
580 
581  if (color_type == COLORED)
582  {
583  unsigned char* input = (unsigned char*)pFrameRGB->data[0];
584  int widthStep = pFrameRGB->linesize[0];
585  for (int i = 0 ; i < height ; i++)
586  {
587  vpImageConvert::RGBToGrey(input + i*widthStep, beginOutput + i*width, (unsigned int)width, 1, false);
588  }
589  }
590 }
591 
596 {
597  if (streamWasOpen)
598  {
599  if (buffer != NULL) {
600  free(buffer);
601  buffer = NULL;
602  }
603 
604  if (color_type == vpFFMPEG::COLORED)
605  av_free(pFrameRGB);
606 
607  else if (color_type == vpFFMPEG::GRAY_SCALED)
608  av_free(pFrameGRAY);
609 
610  // Free the YUV frame
611  av_free(pFrame);
612 
613  // Close the codec
614  if (pCodecCtx) avcodec_close(pCodecCtx);
615 
616  // Close the video file
617 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53,17,0) // libavformat 53.17.0
618  av_close_input_file(pFormatCtx);
619 #else
620  avformat_close_input(&pFormatCtx);
621 #endif
622  }
623  streamWasOpen = false;
624 
625  if (encoderWasOpened)
626  {
627  if(f!=NULL) endWrite();
628 
629  if(buffer!=NULL) delete[] buffer;
630 
631  if(outbuf != NULL) delete[] outbuf;
632 
633  if(picture_buf != NULL) delete[] picture_buf;
634 
635  av_free(pFrameRGB);
636  av_free(pFrame);
637  if (pCodecCtx) avcodec_close(pCodecCtx);
638  }
639 
640  encoderWasOpened = false;
641 
642  if(streamWasInitialized || encoderWasOpened){
643  sws_freeContext (img_convert_ctx);
644  }
645  streamWasInitialized = false;
646 }
647 
663 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,51,110) // libavcodec 54.51.100
664 bool vpFFMPEG::openEncoder(const char *filename, unsigned int w, unsigned int h, CodecID codec)
665 #else
666 bool vpFFMPEG::openEncoder(const char *filename, unsigned int w, unsigned int h, AVCodecID codec)
667 #endif
668 {
669  av_register_all();
670 
671  /* find the mpeg1 video encoder */
672  pCodec = avcodec_find_encoder(codec);
673  if (pCodec == NULL) {
674  fprintf(stderr, "codec not found\n");
675  return false;
676  }
677 
678 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53,5,0) // libavcodec 53.5.0
679  pCodecCtx = avcodec_alloc_context();
680 #else
681  pCodecCtx = avcodec_alloc_context3(NULL);
682 #endif
683 
684 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,34,0)
685  pFrame = avcodec_alloc_frame();
686  pFrameRGB = avcodec_alloc_frame();
687 #else
688  pFrame = av_frame_alloc(); // libavcodec 55.34.1
689  pFrameRGB = av_frame_alloc(); // libavcodec 55.34.1
690 #endif
691 
692  /* put sample parameters */
693  pCodecCtx->bit_rate = (int)bit_rate;
694  /* resolution must be a multiple of two */
695  pCodecCtx->width = (int)w;
696  pCodecCtx->height = (int)h;
697  this->width = (int)w;
698  this->height = (int)h;
699  /* frames per second */
700  pCodecCtx->time_base.num = 1;
701  pCodecCtx->time_base.den = framerate_encoder;
702  pCodecCtx->gop_size = 10; /* emit one intra frame every ten frames */
703  pCodecCtx->max_b_frames=1;
704  pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
705 
706  /* open it */
707 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53,35,0) // libavcodec 53.35.0
708  if (avcodec_open (pCodecCtx, pCodec) < 0) {
709 #else
710  if (avcodec_open2 (pCodecCtx, pCodec, NULL) < 0) {
711 #endif
712  fprintf(stderr, "could not open codec\n");
713  return false;
714  }
715 
716  /* the codec gives us the frame size, in samples */
717 
718  f = fopen(filename, "wb");
719  if (!f) {
720  fprintf(stderr, "could not open %s\n", filename);
721  return false;
722  }
723 
724  outbuf_size = 100000;
725  outbuf = new uint8_t[outbuf_size];
726 
727  numBytes = avpicture_get_size (PIX_FMT_YUV420P,pCodecCtx->width,pCodecCtx->height);
728  picture_buf = new uint8_t[numBytes];
729  avpicture_fill((AVPicture *)pFrame, picture_buf, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
730 
731  numBytes = avpicture_get_size (PIX_FMT_RGB24,pCodecCtx->width,pCodecCtx->height);
732  buffer = new uint8_t[numBytes];
733  avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
734 
735  img_convert_ctx= sws_getContext(pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, pCodecCtx->width,pCodecCtx->height,PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
736 
737  encoderWasOpened = true;
738 
739  return true;
740 }
741 
742 
751 {
752  if (encoderWasOpened == false)
753  {
754  vpTRACE("Couldn't save a frame. The parameters have to be initialized before ");
755  return false;
756  }
757 
758  writeBitmap(I);
759  sws_scale(img_convert_ctx, pFrameRGB->data, pFrameRGB->linesize, 0, pCodecCtx->height, pFrame->data, pFrame->linesize);
760 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,2,100) // libavcodec 54.2.100
761  out_size = avcodec_encode_video(pCodecCtx, outbuf, outbuf_size, pFrame);
762  fwrite(outbuf, 1, (size_t)out_size, f);
763 #else
764  AVPacket pkt;
765  av_init_packet(&pkt);
766  pkt.data = NULL; // packet data will be allocated by the encoder
767  pkt.size = 0;
768 
769  int got_output;
770  int ret = avcodec_encode_video2(pCodecCtx, &pkt, pFrame, &got_output);
771  if (ret < 0) {
772  std::cerr << "Error encoding frame in " << __FILE__ << " " << __LINE__ << " " << __FUNCTION__ << std::endl;
773  return false;
774  }
775  if (got_output) {
776  fwrite(pkt.data, 1, pkt.size, f);
777  av_free_packet(&pkt);
778  }
779 #endif
780  fflush(stdout);
781  return true;
782 }
783 
784 
793 {
794  if (encoderWasOpened == false)
795  {
796  vpTRACE("Couldn't save a frame. The parameters have to be initialized before ");
797  return false;
798  }
799 
800  writeBitmap(I);
801  sws_scale(img_convert_ctx, pFrameRGB->data, pFrameRGB->linesize, 0, pCodecCtx->height, pFrame->data, pFrame->linesize);
802 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,2,100) // libavcodec 54.2.100
803  out_size = avcodec_encode_video(pCodecCtx, outbuf, outbuf_size, pFrame);
804  fwrite(outbuf, 1, (size_t)out_size, f);
805 #else
806  AVPacket pkt;
807  av_init_packet(&pkt);
808  pkt.data = NULL; // packet data will be allocated by the encoder
809  pkt.size = 0;
810 
811  int got_output;
812  int ret = avcodec_encode_video2(pCodecCtx, &pkt, pFrame, &got_output);
813  if (ret < 0) {
814  std::cerr << "Error encoding frame in " << __FILE__ << " " << __LINE__ << " " << __FUNCTION__ << std::endl;
815  return false;
816  }
817  if (got_output) {
818  fwrite(pkt.data, 1, pkt.size, f);
819  av_free_packet(&pkt);
820  }
821 #endif
822 
823  fflush(stdout);
824  return true;
825 }
826 
833 {
834  if (encoderWasOpened == false)
835  {
836  vpTRACE("Couldn't save a frame. The parameters have to be initialized before ");
837  return false;
838  }
839 
840  int ret = 1;
841  while (ret != 0)
842  {
843 
844 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,2,100) // libavcodec 54.2.100
845  ret = avcodec_encode_video(pCodecCtx, outbuf, outbuf_size, NULL);
846  fwrite(outbuf, 1, (size_t)out_size, f);
847 #else
848  AVPacket pkt;
849  av_init_packet(&pkt);
850  pkt.data = NULL; // packet data will be allocated by the encoder
851  pkt.size = 0;
852  int got_output;
853  ret = avcodec_encode_video2(pCodecCtx, &pkt, NULL, &got_output);
854  if (ret < 0) {
855  std::cerr << "Error encoding frame in " << __FILE__ << " " << __LINE__ << " " << __FUNCTION__ << std::endl;
856  return false;
857  }
858  if (got_output) {
859  fwrite(pkt.data, 1, pkt.size, f);
860  av_free_packet(&pkt);
861  }
862 #endif
863  }
864 
865  /*The end of a mpeg file*/
866  outbuf[0] = 0x00;
867  outbuf[1] = 0x00;
868  outbuf[2] = 0x01;
869  outbuf[3] = 0xb7;
870  fwrite(outbuf, 1, 4, f);
871  fclose(f);
872  f = NULL;
873  return true;
874 }
875 
879 void vpFFMPEG::writeBitmap(vpImage<vpRGBa> &I)
880 {
881  unsigned char* beginInput = (unsigned char*)I.bitmap;
882  unsigned char* beginOutput = (unsigned char*)pFrameRGB->data[0];
883  int widthStep = pFrameRGB->linesize[0];
884 
885  for(int i=0 ; i < height ; i++)
886  {
887  unsigned char *input = beginInput + 4 * i * width;
888  unsigned char *output = beginOutput + i * widthStep;
889  for(int j=0 ; j < width ; j++)
890  {
891  *(output++) = *(input);
892  *(output++) = *(input+1);
893  *(output++) = *(input+2);
894 
895  input+=4;
896  }
897  }
898 }
899 
900 
904 void vpFFMPEG::writeBitmap(vpImage<unsigned char> &I)
905 {
906  unsigned char* beginInput = (unsigned char*)I.bitmap;
907  unsigned char* beginOutput = (unsigned char*)pFrameRGB->data[0];
908  int widthStep = pFrameRGB->linesize[0];
909 
910  for(int i=0 ; i < height ; i++)
911  {
912  unsigned char *input = beginInput + i * width;
913  unsigned char *output = beginOutput + i * widthStep;
914  for(int j=0 ; j < width ; j++)
915  {
916  *(output++) = *(input);
917  *(output++) = *(input);
918  *(output++) = *(input);
919 
920  input++;
921  }
922  }
923 }
924 
925 #elif !defined(VISP_BUILD_SHARED_LIBS)
926 // Work arround to avoid warning: libvisp_core.a(vpFFMPEG.cpp.o) has no symbols
927 void dummy_vpFFMPEG() {};
928 #endif
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int size)
Type * bitmap
points toward the bitmap
Definition: vpImage.h:134
bool saveFrame(vpImage< vpRGBa > &I)
Definition: vpFFMPEG.cpp:750
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)
resize the image : Image initialization
Definition: vpImage.h:903
~vpFFMPEG()
Definition: vpFFMPEG.cpp:78
vpFFMPEGColorType
Definition: vpFFMPEG.h:148
void closeStream()
Definition: vpFFMPEG.cpp:595
bool acquire(vpImage< vpRGBa > &I)
Definition: vpFFMPEG.cpp:344
bool initStream()
Definition: vpFFMPEG.cpp:231
bool endWrite()
Definition: vpFFMPEG.cpp:832
bool openEncoder(const char *filename, unsigned int width, unsigned int height, AVCodecID codec=AV_CODEC_ID_MPEG1VIDEO)
Definition: vpFFMPEG.cpp:666