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.
 
 
 
 
 
 

186 rivejä
4.9 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 <avformat.h>
  19. #include <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 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_type = CODEC_TYPE_VIDEO;
  67. ctx->bit_rate = BITRATE;
  68. ctx->time_base.num = 1;
  69. ctx->time_base.den = FPS; /* 25 fps */
  70. ctx->gop_size = FPS / 2;
  71. ctx->pix_fmt = PIX_FMT_YUV420P; /* send YUV 420 */
  72. if(ctx->codec_id == CODEC_ID_MPEG2VIDEO)
  73. ctx->max_b_frames = 2;
  74. if(ctx->codec_id == CODEC_ID_MPEG1VIDEO)
  75. ctx->mb_decision = 2;
  76. if(fmt->oformat->flags & AVFMT_GLOBALHEADER)
  77. ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
  78. if(av_set_parameters(fmt, NULL) < 0)
  79. return EXIT_FAILURE;
  80. codec = avcodec_find_encoder(ctx->codec_id);
  81. if(!codec)
  82. return EXIT_FAILURE;
  83. if(avcodec_open(ctx, codec) < 0)
  84. return EXIT_FAILURE;
  85. frame = avcodec_alloc_frame();
  86. if(!frame)
  87. return EXIT_FAILURE;
  88. tmp = av_malloc(avpicture_get_size(ctx->pix_fmt, ctx->width, ctx->height));
  89. if(!tmp)
  90. return EXIT_FAILURE;
  91. avpicture_fill((AVPicture *)frame, tmp, ctx->pix_fmt,
  92. ctx->width, ctx->height);
  93. if(!(fmt->flags & AVFMT_NOFILE))
  94. if(url_fopen(&fmt->pb, argv[1], URL_WRONLY) < 0)
  95. return EXIT_FAILURE;
  96. len = 64 * 1024 * 1024;
  97. buffer = av_malloc(len);
  98. av_write_header(fmt);
  99. for(;;)
  100. {
  101. uint8_t *start;
  102. int w = 0, h = 0, bytes, pitch;
  103. if(!fgets(file, sizeof(file), stdin))
  104. break;
  105. file[strlen(file) - 1] = '\0';
  106. image = pipi_load(file);
  107. if(!image)
  108. return EXIT_FAILURE;
  109. p = pipi_get_pixels(image, PIPI_PIXELS_RGBA_U8);
  110. start = (uint8_t *)p->pixels;
  111. pitch = p->w * 4;
  112. if(w != p->w || h != p->h)
  113. {
  114. w = p->w;
  115. h = p->h;
  116. if(sws)
  117. sws_freeContext(sws);
  118. sws = NULL;
  119. }
  120. if(!sws)
  121. sws = sws_getContext(w, h, PIX_FMT_RGB32, ctx->width, ctx->height,
  122. ctx->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);
  123. sws_scale(sws, &start, &pitch, 0, h, frame->data, frame->linesize);
  124. pipi_free(image);
  125. bytes = avcodec_encode_video(ctx, buffer, len, frame);
  126. if(bytes <= 0)
  127. continue;
  128. av_init_packet(&packet);
  129. if(ctx->coded_frame->pts != (int64_t)AV_NOPTS_VALUE)
  130. packet.pts = av_rescale_q(ctx->coded_frame->pts,
  131. ctx->time_base, stream->time_base);
  132. if(ctx->coded_frame->key_frame)
  133. packet.flags |= PKT_FLAG_KEY;
  134. packet.stream_index = 0;
  135. packet.data = buffer;
  136. packet.size = bytes;
  137. if(av_interleaved_write_frame(fmt, &packet) < 0)
  138. return EXIT_FAILURE;
  139. }
  140. av_write_trailer(fmt);
  141. avcodec_close(stream->codec);
  142. av_free(frame->data[0]);
  143. av_free(frame);
  144. av_free(buffer);
  145. av_freep(&fmt->streams[0]->codec);
  146. av_freep(&fmt->streams[0]);
  147. if(sws)
  148. sws_freeContext(sws);
  149. if(!(fmt->flags & AVFMT_NOFILE))
  150. url_fclose(fmt->pb);
  151. av_free(fmt);
  152. return EXIT_SUCCESS;
  153. }