|
- /*
- * makemovie read image names from stdin and create a movie
- * Copyright (c) 2009 Sam Hocevar <sam@zoy.org>
- * All Rights Reserved
- *
- * $Id$
- *
- * This program is free software. It comes without any warranty, to
- * the extent permitted by applicable law. You can redistribute it
- * and/or modify it under the terms of the Do What The Fuck You Want
- * To Public License, Version 2, as published by Sam Hocevar. See
- * http://sam.zoy.org/wtfpl/COPYING for more details.
- */
-
- #include "config.h"
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- #include <libavformat/avformat.h>
- #include <libswscale/swscale.h>
-
- #include <pipi.h>
-
- /* These values define a 720x576 anamorphic widescreen image that gets
- * scaled to 1024x576 (16:9). */
- #define WIDTH 720
- #define HEIGHT 576
- #define PAR_NUM 64
- #define PAR_DEN 45
- #define FPS 25
- #define BITRATE 8000000
-
- int main(int argc, char *argv[])
- {
- char file[1024];
- AVPacket packet;
- AVFormatContext *fmt;
- AVCodecContext *ctx;
- AVStream *stream;
- AVCodec *codec;
- AVFrame *frame;
- struct SwsContext *sws = NULL;
- pipi_image_t *image;
- pipi_pixels_t *p;
- uint8_t *buffer, *tmp;
- int f, len;
-
- if(argc < 2)
- return EXIT_FAILURE;
-
- av_register_all();
- fmt = avformat_alloc_context();
- if(!fmt)
- return EXIT_FAILURE;
- snprintf(fmt->filename, sizeof(fmt->filename), "%s", argv[1]);
-
- fmt->oformat = guess_format(NULL, argv[1], NULL);
- if(!fmt->oformat)
- fmt->oformat = guess_format("mpeg", NULL, NULL);
- if(!fmt->oformat)
- return EXIT_FAILURE;
-
- stream = av_new_stream(fmt, 0);
- if(!stream)
- return EXIT_FAILURE;
- stream->sample_aspect_ratio.num = PAR_NUM;
- stream->sample_aspect_ratio.den = PAR_DEN;
-
- ctx = stream->codec;
- ctx->width = WIDTH;
- ctx->height = HEIGHT;
- ctx->sample_aspect_ratio.num = PAR_NUM;
- ctx->sample_aspect_ratio.den = PAR_DEN;
- //ctx->codec_id = fmt->oformat->video_codec;
- //ctx->codec_id = CODEC_ID_FFV1;
- //ctx->codec_id = CODEC_ID_THEORA;
- //ctx->codec_id = CODEC_ID_SNOW;
- //ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; /* Snow */
- ctx->codec_id = CODEC_ID_MJPEG;
- ctx->codec_type = CODEC_TYPE_VIDEO;
- ctx->bit_rate = BITRATE;
- ctx->time_base.num = 1;
- ctx->time_base.den = FPS; /* 25 fps */
- ctx->gop_size = FPS / 2;
- ctx->pix_fmt = PIX_FMT_YUV420P; /* send YUV 420 */
- if(ctx->codec_id == CODEC_ID_MPEG2VIDEO)
- ctx->max_b_frames = 2;
- if(ctx->codec_id == CODEC_ID_MPEG1VIDEO)
- ctx->mb_decision = 2;
- if(fmt->oformat->flags & AVFMT_GLOBALHEADER)
- ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
-
- if(av_set_parameters(fmt, NULL) < 0)
- return EXIT_FAILURE;
-
- codec = avcodec_find_encoder(ctx->codec_id);
- if(!codec)
- return EXIT_FAILURE;
- if(avcodec_open(ctx, codec) < 0)
- return EXIT_FAILURE;
-
- frame = avcodec_alloc_frame();
- if(!frame)
- return EXIT_FAILURE;
- tmp = av_malloc(avpicture_get_size(ctx->pix_fmt, ctx->width, ctx->height));
- if(!tmp)
- return EXIT_FAILURE;
- avpicture_fill((AVPicture *)frame, tmp, ctx->pix_fmt,
- ctx->width, ctx->height);
-
- if(!(fmt->flags & AVFMT_NOFILE))
- if(url_fopen(&fmt->pb, argv[1], URL_WRONLY) < 0)
- return EXIT_FAILURE;
-
- len = 64 * 1024 * 1024;
- buffer = av_malloc(len);
-
- av_write_header(fmt);
-
- for(f = 0; ; f++)
- {
- uint8_t *start;
- int w = 0, h = 0, bytes, pitch;
-
- if(!fgets(file, sizeof(file), stdin))
- break;
- file[strlen(file) - 1] = '\0';
-
- image = pipi_load(file);
- if(!image)
- return EXIT_FAILURE;
- p = pipi_get_pixels(image, PIPI_PIXELS_RGBA_U8);
- start = (uint8_t *)p->pixels;
- pitch = p->w * 4;
-
- if(w != p->w || h != p->h)
- {
- w = p->w;
- h = p->h;
- if(sws)
- sws_freeContext(sws);
- sws = NULL;
- }
-
- if(!sws)
- sws = sws_getContext(w, h, PIX_FMT_RGB32, ctx->width, ctx->height,
- ctx->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);
-
- sws_scale(sws, &start, &pitch, 0, h, frame->data, frame->linesize);
-
- pipi_free(image);
-
- bytes = avcodec_encode_video(ctx, buffer, len, frame);
- if(bytes <= 0)
- continue;
-
- av_init_packet(&packet);
- if(ctx->coded_frame->pts != (int64_t)AV_NOPTS_VALUE)
- packet.pts = av_rescale_q(ctx->coded_frame->pts,
- ctx->time_base, stream->time_base);
- if(ctx->coded_frame->key_frame)
- packet.flags |= PKT_FLAG_KEY;
- packet.stream_index = 0;
- packet.data = buffer;
- packet.size = bytes;
- if(av_interleaved_write_frame(fmt, &packet) < 0)
- return EXIT_FAILURE;
-
- fprintf(stderr, "frame %d\r", f);
- }
-
- fprintf(stderr, "\n");
-
- av_write_trailer(fmt);
-
- avcodec_close(stream->codec);
- av_free(frame->data[0]);
- av_free(frame);
- av_free(buffer);
- av_freep(&fmt->streams[0]->codec);
- av_freep(&fmt->streams[0]);
-
- if(sws)
- sws_freeContext(sws);
- if(!(fmt->flags & AVFMT_NOFILE))
- url_fclose(fmt->pb);
-
- av_free(fmt);
-
- return EXIT_SUCCESS;
- }
|