main.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. 
  2. /**
  3. * 叶海辉
  4. * QQ群121376426
  5. * http://blog.yundiantech.com/
  6. */
  7. extern "C"
  8. {
  9. #include "libavcodec/avcodec.h"
  10. #include "libavformat/avformat.h"
  11. #include "libavutil/pixfmt.h"
  12. #include "libswscale/swscale.h"
  13. }
  14. #include <stdio.h>
  15. ///现在我们需要做的是让SaveFrame函数能把RGB信息定稿到一个PPM格式的文件中。
  16. ///我们将生成一个简单的PPM格式文件,请相信,它是可以工作的。
  17. void SaveFrame(AVFrame *pFrame, int width, int height,int index)
  18. {
  19. FILE *pFile;
  20. char szFilename[32];
  21. int y;
  22. // Open file
  23. sprintf(szFilename, "frame%d.ppm", index);
  24. pFile=fopen(szFilename, "wb");
  25. if(pFile==NULL)
  26. return;
  27. // Write header
  28. fprintf(pFile, "P6\n%d %d\n255\n", width, height);
  29. // Write pixel data
  30. for(y=0; y<height; y++)
  31. {
  32. fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
  33. }
  34. // Close file
  35. fclose(pFile);
  36. }
  37. int main(int argc, char *argv[])
  38. {
  39. char *file_path = "E:\\in.mp4";
  40. AVFormatContext *pFormatCtx;
  41. AVCodecContext *pCodecCtx;
  42. AVCodec *pCodec;
  43. AVFrame *pFrame, *pFrameRGB;
  44. AVPacket *packet;
  45. uint8_t *out_buffer;
  46. static struct SwsContext *img_convert_ctx;
  47. int videoStream, i, numBytes;
  48. int ret, got_picture;
  49. av_register_all(); //初始化FFMPEG 调用了这个才能正常适用编码器和解码器
  50. //Allocate an AVFormatContext.
  51. pFormatCtx = avformat_alloc_context();
  52. if (avformat_open_input(&pFormatCtx, file_path, NULL, NULL) != 0) {
  53. printf("can't open the file. \n");
  54. return -1;
  55. }
  56. if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
  57. printf("Could't find stream infomation.\n");
  58. return -1;
  59. }
  60. videoStream = -1;
  61. ///循环查找视频中包含的流信息,直到找到视频类型的流
  62. ///便将其记录下来 保存到videoStream变量中
  63. ///这里我们现在只处理视频流 音频流先不管他
  64. for (i = 0; i < pFormatCtx->nb_streams; i++) {
  65. if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
  66. videoStream = i;
  67. }
  68. }
  69. ///如果videoStream为-1 说明没有找到视频流
  70. if (videoStream == -1) {
  71. printf("Didn't find a video stream.\n");
  72. return -1;
  73. }
  74. ///查找解码器
  75. pCodecCtx = pFormatCtx->streams[videoStream]->codec;
  76. pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
  77. if (pCodec == NULL) {
  78. printf("Codec not found.\n");
  79. return -1;
  80. }
  81. ///打开解码器
  82. if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
  83. printf("Could not open codec.\n");
  84. return -1;
  85. }
  86. pFrame = av_frame_alloc();
  87. pFrameRGB = av_frame_alloc();
  88. img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
  89. pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
  90. PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
  91. numBytes = avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,pCodecCtx->height);
  92. out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
  93. avpicture_fill((AVPicture *) pFrameRGB, out_buffer, PIX_FMT_RGB24,
  94. pCodecCtx->width, pCodecCtx->height);
  95. int y_size = pCodecCtx->width * pCodecCtx->height;
  96. packet = (AVPacket *) malloc(sizeof(AVPacket)); //分配一个packet
  97. av_new_packet(packet, y_size); //分配packet的数据
  98. av_dump_format(pFormatCtx, 0, file_path, 0); //输出视频信息
  99. int index = 0;
  100. while (1)
  101. {
  102. if (av_read_frame(pFormatCtx, packet) < 0)
  103. {
  104. break; //这里认为视频读取完了
  105. }
  106. if (packet->stream_index == videoStream) {
  107. ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,packet);
  108. if (ret < 0) {
  109. printf("decode error.\n");
  110. return -1;
  111. }
  112. if (got_picture) {
  113. sws_scale(img_convert_ctx,
  114. (uint8_t const * const *) pFrame->data,
  115. pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data,
  116. pFrameRGB->linesize);
  117. SaveFrame(pFrameRGB, pCodecCtx->width,pCodecCtx->height,index++); //保存图片
  118. if (index > 50) return 0; //这里我们就保存50张图片
  119. }
  120. }
  121. av_free_packet(packet);
  122. }
  123. av_free(out_buffer);
  124. av_free(pFrameRGB);
  125. avcodec_close(pCodecCtx);
  126. avformat_close_input(&pFormatCtx);
  127. return 0;
  128. }