22 #include <grass/gis.h>
23 #include <grass/glocale.h>
24 #include <grass/ogsf_proto.h>
25 #include <grass/gstypes.h>
32 #define STREAM_DURATION 5.0
33 #define STREAM_FRAME_RATE 25
34 #define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
35 #define STREAM_PIX_FMT PIX_FMT_YUV420P
37 AVFrame *picture, *tmp_picture;
38 uint8_t *video_outbuf;
39 int frame_count, video_outbuf_size;
55 static AVStream *add_video_stream(AVFormatContext * oc,
int codec_id,
int w,
61 st = av_new_stream(oc, 0);
63 G_warning(_(
"Unable to allocate stream"));
68 c->codec_id = codec_id;
69 c->codec_type = CODEC_TYPE_VIDEO;
80 c->time_base.den = STREAM_FRAME_RATE;
83 c->pix_fmt = STREAM_PIX_FMT;
84 if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
88 if (c->codec_id == CODEC_ID_MPEG1VIDEO) {
95 if (!strcmp(oc->oformat->name,
"mp4") || !strcmp(oc->oformat->name,
"mov")
96 || !strcmp(oc->oformat->name,
"3gp"))
97 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
99 c->flags |= CODEC_FLAG_QSCALE;
100 c->global_quality = st->quality = FF_QP2LAMBDA * 10;
115 static AVFrame *alloc_picture(
int pix_fmt,
int width,
int height)
118 uint8_t *picture_buf;
121 picture = avcodec_alloc_frame();
126 size = avpicture_get_size(pix_fmt, width, height);
127 picture_buf = av_malloc(size);
134 avpicture_fill((AVPicture *) picture, picture_buf,
135 pix_fmt, width, height);
146 static void open_video(AVFormatContext * oc, AVStream * st)
154 codec = avcodec_find_encoder(c->codec_id);
161 if (avcodec_open(c, codec) < 0) {
167 if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
174 video_outbuf_size = 200000;
175 video_outbuf = av_malloc(video_outbuf_size);
179 picture = alloc_picture(c->pix_fmt, c->width, c->height);
181 G_warning(_(
"Unable to allocate picture"));
189 if (c->pix_fmt != PIX_FMT_YUV420P) {
190 tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height);
192 G_warning(_(
"Unable to allocate temporary picture"));
204 static void write_video_frame(AVFormatContext * oc, AVStream * st)
211 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
216 av_init_packet(&pkt);
218 pkt.flags |= PKT_FLAG_KEY;
219 pkt.stream_index = st->index;
220 pkt.data = (uint8_t *) picture;
221 pkt.size =
sizeof(AVPicture);
223 ret = av_write_frame(oc, &pkt);
228 avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);
233 av_init_packet(&pkt);
236 av_rescale_q(c->coded_frame->pts, c->time_base,
238 if (c->coded_frame->key_frame)
239 pkt.flags |= PKT_FLAG_KEY;
240 pkt.stream_index = st->index;
241 pkt.data = video_outbuf;
245 ret = av_write_frame(oc, &pkt);
252 G_warning(_(
"Error while writing video frame"));
264 static void close_video(AVFormatContext * oc, AVStream * st)
266 avcodec_close(st->codec);
267 av_free(picture->data[0]);
270 av_free(tmp_picture->data[0]);
271 av_free(tmp_picture);
273 av_free(video_outbuf);
292 glGetIntegerv(GL_VIEWPORT, tmp);
294 r = tmp[0] + tmp[2] - 1;
296 t = tmp[1] + tmp[3] - 1;
304 fmt = guess_format(
NULL, filename,
NULL);
306 G_warning(_(
"Unable to deduce output format from file extension: using MPEG"));
307 fmt = guess_format(
"mpeg",
NULL,
NULL);
310 G_warning(_(
"Unable to find suitable output format"));
315 oc = av_alloc_format_context();
321 snprintf(oc->filename,
sizeof(oc->filename),
"%s", filename);
326 fmt->video_codec = CODEC_ID_XVID;
330 if (fmt->video_codec != CODEC_ID_NONE) {
332 add_video_stream(oc, fmt->video_codec, (r - l + 1), (t - b + 1));
336 if (av_set_parameters(oc,
NULL) < 0) {
337 G_warning(_(
"Invalid output format parameters"));
341 dump_format(oc, 0, filename, 1);
346 open_video(oc, video_st);
349 if (!(fmt->flags & AVFMT_NOFILE)) {
350 if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
351 G_warning(_(
"Unable to open <%s>"), filename);
361 G_warning(_(
"NVIZ has not been built with MPEG output support"));
377 unsigned int xsize, ysize;
380 unsigned char *pixbuf;
384 for (y = ysize - 1; y >= 0; y--) {
385 for (x = 0; x < xsize; x++) {
386 unsigned char r = pixbuf[(y * xsize + x) * 4 + 0];
387 unsigned char g = pixbuf[(y * xsize + x) * 4 + 1];
388 unsigned char b = pixbuf[(y * xsize + x) * 4 + 2];
390 yy = (0.257 *
r) + (0.504 * g) + (0.098 *
b) + 16;;
391 vv = (0.439 *
r) - (0.368 * g) - (0.071 *
b) + 128;
392 uu = -(0.148 *
r) - (0.291 * g) + (0.439 *
b) + 128;
394 picture->data[0][xy] = yy;
396 if ((x % 2) && (y % 2)) {
397 picture->data[1][xy_uv] = uu;
398 picture->data[2][xy_uv] = vv;
408 write_video_frame(oc, video_st);
426 close_video(oc, video_st);
429 av_write_trailer(oc);
432 for (i = 0; i < oc->nb_streams; i++) {
433 av_freep(&oc->streams[i]->codec);
434 av_freep(&oc->streams[i]);
437 if (!(fmt->flags & AVFMT_NOFILE)) {
439 #if (LIBAVFORMAT_VERSION_INT>>16) < 52
450 G_debug(3,
"Closed MPEG stream");