GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gsd_img_mpeg.c
Go to the documentation of this file.
1 
18 #include <stdlib.h>
19 #include <string.h>
20 
21 #include <grass/gis.h>
22 #include <grass/glocale.h>
23 #include <grass/ogsf_proto.h>
24 #include <grass/gstypes.h>
25 
26 /* FFMPEG stuff */
27 #ifdef HAVE_FFMPEG
28 #include <avformat.h>
29 #include <avio.h>
30 #if LIBAVUTIL_VERSION_MAJOR < 51
31 #include <avutil.h>
32 #else
33 /* libavutil 51.22.1's avutil.h doesn't include libavutil/mathematics.h */
34 #include <mathematics.h>
35 #endif
36 
37 /* 5 seconds stream duration */
38 #define STREAM_DURATION 5.0
39 #define STREAM_FRAME_RATE 25 /* 25 images/s */
40 #define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
41 #define STREAM_PIX_FMT PIX_FMT_YUV420P /* default pix_fmt */
42 
43 AVFrame *picture, *tmp_picture;
44 uint8_t *video_outbuf;
45 int frame_count, video_outbuf_size;
46 
47 AVOutputFormat *fmt;
48 AVFormatContext *oc;
49 AVStream *video_st;
50 
61 static AVStream *add_video_stream(AVFormatContext * oc, int codec_id, int w,
62  int h)
63 {
64  AVCodecContext *c;
65  AVStream *st;
66 
67 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 112, 0)
68  st = av_new_stream(oc, 0);
69 #else
70  st = avformat_new_stream(oc, NULL);
71 #endif
72  if (!st) {
73  G_warning(_("Unable to allocate stream"));
74  return NULL;
75  }
76 
77  c = st->codec;
78  c->codec_id = codec_id;
79 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52, 123, 0)
80  c->codec_type = CODEC_TYPE_VIDEO;
81 #else
82  c->codec_type = AVMEDIA_TYPE_VIDEO;
83 #endif
84 
85  /* put sample parameters */
86  c->bit_rate = 400000;
87  /* resolution must be a multiple of two */
88  c->width = w;
89  c->height = h;
90  /* time base: this is the fundamental unit of time (in seconds) in terms
91  of which frame timestamps are represented. for fixed-fps content,
92  timebase should be 1/framerate and timestamp increments should be
93  identically 1. */
94  c->time_base.den = STREAM_FRAME_RATE;
95  c->time_base.num = 1;
96  c->gop_size = 12; /* emit one intra frame every twelve frames at most */
97  c->pix_fmt = STREAM_PIX_FMT;
98  if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
99  /* just for testing, we also add B frames */
100  c->max_b_frames = 2;
101  }
102  if (c->codec_id == CODEC_ID_MPEG1VIDEO) {
103  /* Needed to avoid using macroblocks in which some coeffs overflow.
104  This does not happen with normal video, it just happens here as
105  the motion of the chroma plane does not match the luma plane. */
106  c->mb_decision = 2;
107  }
108  /* some formats want stream headers to be separate */
109  if (!strcmp(oc->oformat->name, "mp4") || !strcmp(oc->oformat->name, "mov")
110  || !strcmp(oc->oformat->name, "3gp"))
111  c->flags |= CODEC_FLAG_GLOBAL_HEADER;
112 
113  c->flags |= CODEC_FLAG_QSCALE;
114 
115  /* Quality, as it has been removed from AVCodecContext and put in AVVideoFrame. */
116 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 100, 0)
117  c->global_quality = st->quality = FF_QP2LAMBDA * 10;
118 #else
119  c->global_quality = FF_QP2LAMBDA * 10;
120 #endif
121 
122  return st;
123 }
124 
135 static AVFrame *alloc_picture(int pix_fmt, int width, int height)
136 {
137  AVFrame *picture;
138  uint8_t *picture_buf;
139  int size;
140 
141  picture = avcodec_alloc_frame();
142 
143  if (!picture)
144  return NULL;
145 
146  size = avpicture_get_size(pix_fmt, width, height);
147  picture_buf = av_malloc(size);
148 
149  if (!picture_buf) {
150  av_free(picture);
151  return NULL;
152  }
153 
154  avpicture_fill((AVPicture *) picture, picture_buf,
155  pix_fmt, width, height);
156 
157  return picture;
158 }
159 
166 static void open_video(AVFormatContext * oc, AVStream * st)
167 {
168  AVCodec *codec;
169  AVCodecContext *c;
170 
171  c = st->codec;
172 
173  /* find the video encoder */
174  codec = avcodec_find_encoder(c->codec_id);
175  if (!codec) {
176  G_warning(_("Video codec not found"));
177  return;
178  }
179 
180  /* open the codec */
181 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 100, 0)
182  if (avcodec_open(c, codec) < 0) {
183 #else
184  if (avcodec_open2(c, codec, NULL) < 0) {
185 #endif
186  G_warning(_("Unable to open codec"));
187  return;
188  }
189 
190  video_outbuf = NULL;
191  if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
192  /* allocate output buffer */
193  /* XXX: API change will be done */
194  /* buffers passed into lav* can be allocated any way you prefer,
195  as long as they're aligned enough for the architecture, and
196  they're freed appropriately (such as using av_free for buffers
197  allocated with av_malloc) */
198  video_outbuf_size = 200000;
199  video_outbuf = av_malloc(video_outbuf_size);
200  }
201 
202  /* allocate the encoded raw picture */
203  picture = alloc_picture(c->pix_fmt, c->width, c->height);
204  if (!picture) {
205  G_warning(_("Unable to allocate picture"));
206  return;
207  }
208 
209  /* if the output format is not YUV420P, then a temporary YUV420P
210  picture is needed too. It is then converted to the required
211  output format */
212  tmp_picture = NULL;
213  if (c->pix_fmt != PIX_FMT_YUV420P) {
214  tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height);
215  if (!tmp_picture) {
216  G_warning(_("Unable to allocate temporary picture"));
217  return;
218  }
219  }
220 }
221 
228 static void write_video_frame(AVFormatContext * oc, AVStream * st)
229 {
230  int out_size, ret;
231  AVCodecContext *c;
232 
233  c = st->codec;
234 
235  if (oc->oformat->flags & AVFMT_RAWPICTURE) {
236  /* raw video case. The API will change slightly in the near
237  future for that */
238  AVPacket pkt;
239 
240  av_init_packet(&pkt);
241 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 32, 0)
242  pkt.flags |= PKT_FLAG_KEY;
243 #else
244  pkt.flags |= AV_PKT_FLAG_KEY;
245 #endif
246  pkt.stream_index = st->index;
247  pkt.data = (uint8_t *) picture;
248  pkt.size = sizeof(AVPicture);
249 
250  ret = av_write_frame(oc, &pkt);
251  }
252  else {
253  /* encode the image */
254  out_size =
255  avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);
256  /* if zero size, it means the image was buffered */
257  if (out_size > 0) {
258  AVPacket pkt;
259 
260  av_init_packet(&pkt);
261 
262  pkt.pts =
263  av_rescale_q(c->coded_frame->pts, c->time_base,
264  st->time_base);
265  if (c->coded_frame->key_frame)
266 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 32, 0)
267  pkt.flags |= PKT_FLAG_KEY;
268 #else
269  pkt.flags |= AV_PKT_FLAG_KEY;
270 #endif
271  pkt.stream_index = st->index;
272  pkt.data = video_outbuf;
273  pkt.size = out_size;
274 
275  /* write the compressed frame in the media file */
276  ret = av_write_frame(oc, &pkt);
277  }
278  else {
279  ret = 0;
280  }
281  }
282  if (ret != 0) {
283  G_warning(_("Error while writing video frame"));
284  return;
285  }
286  frame_count++;
287 }
288 
295 static void close_video(AVStream * st)
296 {
297  avcodec_close(st->codec);
298  av_free(picture->data[0]);
299  av_free(picture);
300  if (tmp_picture) {
301  av_free(tmp_picture->data[0]);
302  av_free(tmp_picture);
303  }
304  av_free(video_outbuf);
305 }
306 
307 #endif
308 
317 int gsd_init_mpeg(const char *filename)
318 {
319 #ifdef HAVE_FFMPEG
320  GLuint l, r, b, t;
321  GLint tmp[4];
322 
323  glGetIntegerv(GL_VIEWPORT, tmp);
324  l = tmp[0];
325  r = tmp[0] + tmp[2] - 1;
326  b = tmp[1];
327  t = tmp[1] + tmp[3] - 1;
328 
329  G_verbose_message(_("Opening MPEG stream <%s>..."), filename);
330 
331  /* initialize libavcodec, and register all codecs and formats */
332  av_register_all();
333 
334  /* auto detect the output format from the name. default is mpeg. */
335 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 32, 0)
336  fmt = guess_format(NULL, filename, NULL);
337 #else
338  fmt = av_guess_format(NULL, filename, NULL);
339 #endif
340  if (!fmt) {
341  G_warning(_("Unable to deduce output format from file extension: using MPEG"));
342 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 32, 0)
343  fmt = guess_format("mpeg", NULL, NULL);
344 #else
345  fmt = av_guess_format("mpeg", NULL, NULL);
346 #endif
347  }
348  if (!fmt) {
349  G_warning(_("Unable to find suitable output format"));
350  return (-1);
351  }
352 
353  /* allocate the output media context */
354  oc = avformat_alloc_context();
355  if (!oc) {
356  G_warning(_("Out of memory"));
357  return (-1);
358  }
359  oc->oformat = fmt;
360  snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
361 
362  /* if you want to hardcode the codec (eg #ifdef USE_XVID)
363  this may be the place to do it (?????) */
364 #ifdef USE_XVID
365  fmt->video_codec = CODEC_ID_XVID;
366 #endif
367 
368  video_st = NULL;
369  if (fmt->video_codec != CODEC_ID_NONE) {
370  video_st =
371  add_video_stream(oc, fmt->video_codec, (r - l + 1), (t - b + 1));
372  }
373 
374  /* set the output parameters (must be done even if no parameters). */
375 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 100, 0)
376  if (av_set_parameters(oc, NULL) < 0) {
377 #else
378  if (avformat_write_header(oc, NULL) < 0) {
379 #endif
380  G_warning(_("Invalid output format parameters"));
381  return -1;
382  }
383 
384 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 100, 0)
385  dump_format(oc, 0, filename, 1);
386 #else
387  av_dump_format(oc, 0, filename, 1);
388 #endif
389 
390  /* now that all the parameters are set, we can open the audio and
391  video codecs and allocate the necessary encode buffers */
392  if (video_st)
393  open_video(oc, video_st);
394 
395  /* open the output file, if needed */
396  if (!(fmt->flags & AVFMT_NOFILE)) {
397 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 112, 0)
398  if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
399 #else
400  if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0) {
401 #endif
402  G_warning(_("Unable to open <%s>"), filename);
403  return (-1);
404  }
405  }
406 
407  /* write the stream header, if any */
408 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 100, 0)
409  av_write_header(oc);
410 #else
411  avformat_write_header(oc, NULL);
412 #endif
413 
414 #else
415  G_warning(_("OGSF library has not been built with MPEG output support"));
416  return -1;
417 #endif
418  return 0;
419 }
420 
429 {
430 #ifdef HAVE_FFMPEG
431  unsigned int xsize, ysize, x;
432  int y, xy, xy_uv;
433  int yy, uu, vv;
434  unsigned char *pixbuf;
435 
436  gsd_getimage(&pixbuf, &xsize, &ysize);
437  xy = xy_uv = 0;
438  for (y = ysize - 1; y >= 0; y--) {
439  for (x = 0; x < xsize; x++) {
440  unsigned char r = pixbuf[(y * xsize + x) * 4 + 0];
441  unsigned char g = pixbuf[(y * xsize + x) * 4 + 1];
442  unsigned char b = pixbuf[(y * xsize + x) * 4 + 2];
443 
444  yy = (0.257 * r) + (0.504 * g) + (0.098 * b) + 16;;
445  vv = (0.439 * r) - (0.368 * g) - (0.071 * b) + 128;
446  uu = -(0.148 * r) - (0.291 * g) + (0.439 * b) + 128;
447  fflush(stdout);
448  picture->data[0][xy] = yy;
449 
450  if ((x % 2) && (y % 2)) {
451  picture->data[1][xy_uv] = uu;
452  picture->data[2][xy_uv] = vv;
453  xy_uv++;
454  }
455 
456  xy++;
457  }
458 
459  }
460  G_free(pixbuf);
461 
462  write_video_frame(oc, video_st);
463 
464 
465 #endif
466 
467  return (0);
468 }
469 
475 int gsd_close_mpeg(void)
476 {
477 #ifdef HAVE_FFMPEG
478  unsigned int i;
479 
480  close_video(video_st);
481 
482  /* write the trailer, if any */
483  av_write_trailer(oc);
484 
485  /* free the streams */
486  for (i = 0; i < oc->nb_streams; i++) {
487  av_freep(&oc->streams[i]->codec);
488  av_freep(&oc->streams[i]);
489  }
490 
491  if (!(fmt->flags & AVFMT_NOFILE)) {
492  /* close the output file */
493 #if (LIBAVFORMAT_VERSION_INT>>16) < 52
494  url_fclose(&oc->pb);
495 #elif LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 100, 0)
496  url_fclose(oc->pb);
497 #else
498  avio_close(oc->pb);
499 #endif
500  }
501 
502  /* free the stream */
503  av_free(oc);
504 
505 
506  G_debug(3, "Closed MPEG stream");
507 #endif
508 
509  return 0;
510 }
void G_free(void *buf)
Free allocated memory.
Definition: gis/alloc.c:142
int l
Definition: dataquad.c:292
float b
Definition: named_colr.c:8
int gsd_close_mpeg(void)
Close the mpeg, free buffer, and close file.
Definition: gsd_img_mpeg.c:475
float r
Definition: named_colr.c:8
tuple width
int y
Definition: plot.c:34
tuple size
value.Bind(wx.EVT_TEXT, self.OnVolumeIsosurfMap)
Definition: tools.py:2334
void G_verbose_message(const char *msg,...)
Print a message to stderr but only if module is in verbose mode.
Definition: lib/gis/error.c:95
int gsd_init_mpeg(const char *filename)
Initialize FAME setup mpeg defaults and open file for writing.
Definition: gsd_img_mpeg.c:317
int gsd_write_mpegframe(void)
Get RGB pixbuf and convert to YUV 4:2:0.
Definition: gsd_img_mpeg.c:428
float g
Definition: named_colr.c:8
return NULL
Definition: dbfopen.c:1394
G_warning("category support for [%s] in mapset [%s] %s", name, mapset, type)
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: gis/debug.c:51
int gsd_getimage(unsigned char **pixbuf, unsigned int *xsize, unsigned int *ysize)
Get image of current GL screen.
Definition: gsd_prim.c:893
int height
tuple h
panel.defaultSize = wx.CheckBox(panel, id = wx.ID_ANY, label = _(&quot;Use default size&quot;)) panel...