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.
 
 
 
 
 
 

147 line
3.8 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;
  36. if(argc < 2)
  37. return EXIT_FAILURE;
  38. /* Ensure our linear YUV values do not get gamma-corrected */
  39. pipi_set_gamma(1.0);
  40. parser = strrchr(argv[1], '/');
  41. strcpy(fmtstr, parser ? parser + 1 : argv[1]);
  42. parser = strrchr(fmtstr, '.');
  43. if(parser)
  44. *parser = '\0';
  45. strcat(fmtstr, "-%06i.png");
  46. av_register_all();
  47. if(av_open_input_file(&fmt, argv[1], NULL, 0, NULL) != 0)
  48. return EXIT_FAILURE;
  49. if(av_find_stream_info(fmt) < 0 )
  50. return EXIT_FAILURE;
  51. stream = -1;
  52. for(i = 0; stream == -1 && i < (int)fmt->nb_streams; i++)
  53. if(fmt->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
  54. stream = i;
  55. if(stream == -1)
  56. return EXIT_FAILURE;
  57. ctx = fmt->streams[stream]->codec;
  58. codec = avcodec_find_decoder(ctx->codec_id);
  59. if(codec == NULL)
  60. return EXIT_FAILURE;
  61. if(avcodec_open(ctx, codec) < 0)
  62. return EXIT_FAILURE;
  63. frame = avcodec_alloc_frame();
  64. for(;;)
  65. {
  66. int finished, ret, x, y;
  67. ret = av_read_frame(fmt, &packet);
  68. if(ret < 0)
  69. break;
  70. if(packet.stream_index != stream)
  71. {
  72. av_free_packet(&packet);
  73. continue;
  74. }
  75. avcodec_decode_video(ctx, frame, &finished, packet.data, packet.size);
  76. if(!finished)
  77. {
  78. av_free_packet(&packet);
  79. continue;
  80. }
  81. if(!sws)
  82. {
  83. sws = sws_getContext(ctx->width, ctx->height, ctx->pix_fmt,
  84. ctx->width, ctx->height, PIX_FMT_YUV444P,
  85. SWS_FAST_BILINEAR, NULL, NULL, NULL);
  86. pitch[0] = ctx->width;
  87. pitch[1] = ctx->width;
  88. pitch[2] = ctx->width;
  89. pitch[3] = 0;
  90. dst[0] = malloc(ctx->width * ctx->height * 3);
  91. dst[1] = dst[0] + ctx->width * ctx->height;
  92. dst[2] = dst[1] + ctx->width * ctx->height;
  93. dst[3] = NULL;
  94. image = pipi_new(ctx->width, ctx->height);
  95. }
  96. sws_scale(sws, (uint8_t const **)frame->data, frame->linesize, 0,
  97. ctx->height, dst, pitch);
  98. p = pipi_get_pixels(image, PIPI_PIXELS_RGBA_U8);
  99. data = (uint8_t *)p->pixels;
  100. for (y = 0; y < ctx->height; y++)
  101. {
  102. int off = y * ctx->width;
  103. for (x = 0; x < ctx->width; x++, off++)
  104. {
  105. data[4 * off] = dst[0][off];
  106. data[4 * off + 1] = dst[1][off];
  107. data[4 * off + 2] = dst[2][off];
  108. data[4 * off + 3] = 0xff;
  109. }
  110. }
  111. {
  112. char buf[1024];
  113. sprintf(buf, fmtstr, k++);
  114. printf("saving in %s\n", buf);
  115. pipi_save(image, buf);
  116. }
  117. av_free_packet(&packet);
  118. }
  119. return EXIT_SUCCESS;
  120. }