Browse Source

makemovie: new example program; this utility reads a list of images from

stdin and encodes them into a movie (name specified on the command line).

git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@3413 92316355-f0b4-4df1-b90c-862c8a59935f
master
sam 16 years ago
parent
commit
9ebe671bd6
2 changed files with 192 additions and 1 deletions
  1. +7
    -1
      examples/Makefile.am
  2. +185
    -0
      examples/makemovie.c

+ 7
- 1
examples/Makefile.am View File

@@ -3,7 +3,7 @@
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/pipi -I../pipi

noinst_PROGRAMS = edd img2rubik sharpen floodfill line bezier histogram \
colorstring $(storyboard)
colorstring $(makemovie) $(storyboard)

edd_SOURCES = edd.c
edd_LDADD = ../pipi/libpipi.la
@@ -30,8 +30,14 @@ colorstring_SOURCES = colorstring.c
colorstring_LDADD = ../pipi/libpipi.la

if USE_FFMPEG
makemovie = makemovie
storyboard = storyboard
endif
makemovie_SOURCES = makemovie.c
makemovie_LDADD = ../pipi/libpipi.la
makemovie_CFLAGS = $(LIBAVCODEC_CFLAGS) $(LIBAVFORMAT_CFLAGS) $(LIBSWSCALE_CFLAGS)
makemovie_LDFLAGS = $(LIBAVCODEC_LIBS) $(LIBAVFORMAT_LIBS) $(LIBSWSCALE_LIBS)

storyboard_SOURCES = storyboard.c
storyboard_LDADD = ../pipi/libpipi.la
storyboard_CFLAGS = $(LIBAVCODEC_CFLAGS) $(LIBAVFORMAT_CFLAGS) $(LIBSWSCALE_CFLAGS)


+ 185
- 0
examples/makemovie.c View File

@@ -0,0 +1,185 @@
/*
* 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 <avformat.h>
#include <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 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_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(;;)
{
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;
}

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;
}


Loading…
Cancel
Save