/* * makemovie read image names from stdin and create a movie * Copyright (c) 2009 Sam Hocevar * 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 #include #include #include #include #include /* 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; }