You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

195 lines
5.2 KiB

  1. /*
  2. * makemovie read image names from stdin and create a movie
  3. * Copyright (c) 2009 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This program is free software. It comes without any warranty, to
  9. * the extent permitted by applicable law. You can redistribute it
  10. * and/or modify it under the terms of the Do What The Fuck You Want
  11. * To Public License, Version 2, as published by Sam Hocevar. See
  12. * http://sam.zoy.org/wtfpl/COPYING for more details.
  13. */
  14. #include "config.h"
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <libavformat/avformat.h>
  19. #include <libswscale/swscale.h>
  20. #include <pipi.h>
  21. /* These values define a 720x576 anamorphic widescreen image that gets
  22. * scaled to 1024x576 (16:9). */
  23. #define WIDTH 720
  24. #define HEIGHT 576
  25. #define PAR_NUM 64
  26. #define PAR_DEN 45
  27. #define FPS 25
  28. #define BITRATE 8000000
  29. int main(int argc, char *argv[])
  30. {
  31. char file[1024];
  32. AVPacket packet;
  33. AVFormatContext *fmt;
  34. AVCodecContext *ctx;
  35. AVStream *stream;
  36. AVCodec *codec;
  37. AVFrame *frame;
  38. struct SwsContext *sws = NULL;
  39. pipi_image_t *image;
  40. pipi_pixels_t *p;
  41. uint8_t *buffer, *tmp;
  42. int f, len;
  43. if(argc < 2)
  44. return EXIT_FAILURE;
  45. av_register_all();
  46. fmt = avformat_alloc_context();
  47. if(!fmt)
  48. return EXIT_FAILURE;
  49. snprintf(fmt->filename, sizeof(fmt->filename), "%s", argv[1]);
  50. fmt->oformat = guess_format(NULL, argv[1], NULL);
  51. if(!fmt->oformat)
  52. fmt->oformat = guess_format("mpeg", NULL, NULL);
  53. if(!fmt->oformat)
  54. return EXIT_FAILURE;
  55. stream = av_new_stream(fmt, 0);
  56. if(!stream)
  57. return EXIT_FAILURE;
  58. stream->sample_aspect_ratio.num = PAR_NUM;
  59. stream->sample_aspect_ratio.den = PAR_DEN;
  60. ctx = stream->codec;
  61. ctx->width = WIDTH;
  62. ctx->height = HEIGHT;
  63. ctx->sample_aspect_ratio.num = PAR_NUM;
  64. ctx->sample_aspect_ratio.den = PAR_DEN;
  65. //ctx->codec_id = fmt->oformat->video_codec;
  66. //ctx->codec_id = CODEC_ID_FFV1;
  67. //ctx->codec_id = CODEC_ID_THEORA;
  68. //ctx->codec_id = CODEC_ID_SNOW;
  69. //ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; /* Snow */
  70. ctx->codec_id = CODEC_ID_MJPEG;
  71. ctx->codec_type = CODEC_TYPE_VIDEO;
  72. ctx->bit_rate = BITRATE;
  73. ctx->time_base.num = 1;
  74. ctx->time_base.den = FPS; /* 25 fps */
  75. ctx->gop_size = FPS / 2;
  76. ctx->pix_fmt = PIX_FMT_YUV420P; /* send YUV 420 */
  77. if(ctx->codec_id == CODEC_ID_MPEG2VIDEO)
  78. ctx->max_b_frames = 2;
  79. if(ctx->codec_id == CODEC_ID_MPEG1VIDEO)
  80. ctx->mb_decision = 2;
  81. if(fmt->oformat->flags & AVFMT_GLOBALHEADER)
  82. ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
  83. if(av_set_parameters(fmt, NULL) < 0)
  84. return EXIT_FAILURE;
  85. codec = avcodec_find_encoder(ctx->codec_id);
  86. if(!codec)
  87. return EXIT_FAILURE;
  88. if(avcodec_open(ctx, codec) < 0)
  89. return EXIT_FAILURE;
  90. frame = avcodec_alloc_frame();
  91. if(!frame)
  92. return EXIT_FAILURE;
  93. tmp = av_malloc(avpicture_get_size(ctx->pix_fmt, ctx->width, ctx->height));
  94. if(!tmp)
  95. return EXIT_FAILURE;
  96. avpicture_fill((AVPicture *)frame, tmp, ctx->pix_fmt,
  97. ctx->width, ctx->height);
  98. if(!(fmt->flags & AVFMT_NOFILE))
  99. if(url_fopen(&fmt->pb, argv[1], URL_WRONLY) < 0)
  100. return EXIT_FAILURE;
  101. len = 64 * 1024 * 1024;
  102. buffer = av_malloc(len);
  103. av_write_header(fmt);
  104. for(f = 0; ; f++)
  105. {
  106. uint8_t *start;
  107. int w = 0, h = 0, bytes, pitch;
  108. if(!fgets(file, sizeof(file), stdin))
  109. break;
  110. file[strlen(file) - 1] = '\0';
  111. image = pipi_load(file);
  112. if(!image)
  113. return EXIT_FAILURE;
  114. p = pipi_get_pixels(image, PIPI_PIXELS_RGBA_U8);
  115. start = (uint8_t *)p->pixels;
  116. pitch = p->w * 4;
  117. if(w != p->w || h != p->h)
  118. {
  119. w = p->w;
  120. h = p->h;
  121. if(sws)
  122. sws_freeContext(sws);
  123. sws = NULL;
  124. }
  125. if(!sws)
  126. sws = sws_getContext(w, h, PIX_FMT_RGB32, ctx->width, ctx->height,
  127. ctx->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);
  128. sws_scale(sws, &start, &pitch, 0, h, frame->data, frame->linesize);
  129. pipi_free(image);
  130. bytes = avcodec_encode_video(ctx, buffer, len, frame);
  131. if(bytes <= 0)
  132. continue;
  133. av_init_packet(&packet);
  134. if(ctx->coded_frame->pts != (int64_t)AV_NOPTS_VALUE)
  135. packet.pts = av_rescale_q(ctx->coded_frame->pts,
  136. ctx->time_base, stream->time_base);
  137. if(ctx->coded_frame->key_frame)
  138. packet.flags |= PKT_FLAG_KEY;
  139. packet.stream_index = 0;
  140. packet.data = buffer;
  141. packet.size = bytes;
  142. if(av_interleaved_write_frame(fmt, &packet) < 0)
  143. return EXIT_FAILURE;
  144. fprintf(stderr, "frame %d\r", f);
  145. }
  146. fprintf(stderr, "\n");
  147. av_write_trailer(fmt);
  148. avcodec_close(stream->codec);
  149. av_free(frame->data[0]);
  150. av_free(frame);
  151. av_free(buffer);
  152. av_freep(&fmt->streams[0]->codec);
  153. av_freep(&fmt->streams[0]);
  154. if(sws)
  155. sws_freeContext(sws);
  156. if(!(fmt->flags & AVFMT_NOFILE))
  157. url_fclose(fmt->pb);
  158. av_free(fmt);
  159. return EXIT_SUCCESS;
  160. }