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.
 
 
 
 
 
 

162 lines
4.4 KiB

  1. /*
  2. * dumpmovie dump a movie into YUV PNG files
  3. * Copyright (c) 2010 Sam Hocevar <sam@hocevar.net>
  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 <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <libavcodec/avcodec.h>
  19. #include <libavformat/avformat.h>
  20. #include <libswscale/swscale.h>
  21. #include <pipi.h>
  22. int main(int argc, char *argv[])
  23. {
  24. char fmtstr[1024];
  25. AVPacket packet;
  26. AVFormatContext *fmt;
  27. AVCodecContext *ctx;
  28. AVCodec *codec;
  29. AVFrame *frame;
  30. struct SwsContext *sws = NULL;
  31. pipi_image_t *image = NULL;
  32. pipi_pixels_t *p;
  33. uint8_t *dst[4], *data = NULL;
  34. char *parser;
  35. int stream, pitch[4], i, k = 0, nframes = -1;
  36. double skip_seconds = 0.0;
  37. if (argc < 2)
  38. return EXIT_FAILURE;
  39. if (argc > 2)
  40. skip_seconds = atof(argv[2]);
  41. if (argc > 3)
  42. nframes = atoi(argv[3]);
  43. /* Ensure our linear YUV values do not get gamma-corrected */
  44. pipi_set_gamma(1.0);
  45. parser = strrchr(argv[1], '/');
  46. strcpy(fmtstr, parser ? parser + 1 : argv[1]);
  47. parser = strrchr(fmtstr, '.');
  48. if(parser)
  49. *parser = '\0';
  50. strcat(fmtstr, "-%06i.png");
  51. av_register_all();
  52. if(av_open_input_file(&fmt, argv[1], NULL, 0, NULL) != 0)
  53. return EXIT_FAILURE;
  54. if(av_find_stream_info(fmt) < 0 )
  55. return EXIT_FAILURE;
  56. stream = -1;
  57. for(i = 0; stream == -1 && i < (int)fmt->nb_streams; i++)
  58. if(fmt->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
  59. stream = i;
  60. if(stream == -1)
  61. return EXIT_FAILURE;
  62. ctx = fmt->streams[stream]->codec;
  63. codec = avcodec_find_decoder(ctx->codec_id);
  64. if(codec == NULL)
  65. return EXIT_FAILURE;
  66. if(avcodec_open(ctx, codec) < 0)
  67. return EXIT_FAILURE;
  68. skip_seconds /= av_q2d(fmt->streams[stream]->time_base);
  69. av_seek_frame(fmt, stream, (int)(skip_seconds + 0.5), SEEK_SET);
  70. //avformat_seek_file(fmt, stream, skip_bytes, skip_bytes,
  71. // skip_bytes, AVSEEK_FLAG_BYTE);
  72. frame = avcodec_alloc_frame();
  73. for (k = 0; k < nframes || nframes == -1; /* k incremented below */)
  74. {
  75. int finished, ret, x, y;
  76. ret = av_read_frame(fmt, &packet);
  77. if(ret < 0)
  78. break;
  79. if(packet.stream_index != stream)
  80. {
  81. av_free_packet(&packet);
  82. continue;
  83. }
  84. avcodec_decode_video(ctx, frame, &finished, packet.data, packet.size);
  85. if(!finished)
  86. {
  87. av_free_packet(&packet);
  88. continue;
  89. }
  90. if(!sws)
  91. {
  92. sws = sws_getContext(ctx->width, ctx->height, ctx->pix_fmt,
  93. ctx->width, ctx->height, PIX_FMT_YUV444P,
  94. SWS_FAST_BILINEAR, NULL, NULL, NULL);
  95. pitch[0] = ctx->width;
  96. pitch[1] = ctx->width;
  97. pitch[2] = ctx->width;
  98. pitch[3] = 0;
  99. dst[0] = malloc(ctx->width * ctx->height * 3);
  100. dst[1] = dst[0] + ctx->width * ctx->height;
  101. dst[2] = dst[1] + ctx->width * ctx->height;
  102. dst[3] = NULL;
  103. image = pipi_new(ctx->width, ctx->height);
  104. }
  105. {
  106. char buf[1024];
  107. sprintf(buf, fmtstr, k);
  108. printf("saving in %s\n", buf);
  109. sws_scale(sws, (uint8_t const **)frame->data, frame->linesize, 0,
  110. ctx->height, dst, pitch);
  111. p = pipi_get_pixels(image, PIPI_PIXELS_RGBA_U8);
  112. data = (uint8_t *)p->pixels;
  113. for (y = 0; y < ctx->height; y++)
  114. {
  115. int off = y * ctx->width;
  116. for (x = 0; x < ctx->width; x++, off++)
  117. {
  118. /* Reorder components to store YUVA */
  119. data[4 * off] = dst[0][off];
  120. data[4 * off + 1] = dst[2][off];
  121. data[4 * off + 2] = dst[1][off];
  122. data[4 * off + 3] = 0xff;
  123. }
  124. }
  125. pipi_save(image, buf);
  126. }
  127. av_free_packet(&packet);
  128. k++;
  129. }
  130. return EXIT_SUCCESS;
  131. }