|  | @@ -1,10 +1,11 @@
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  |   * 叶海辉
 | 
	
		
			
				|  |  |   * QQ群121376426
 | 
	
		
			
				|  |  |   * http://blog.yundiantech.com/
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#include "videoplayer.h"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  extern "C"
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      #include "libavcodec/avcodec.h"
 | 
	
	
		
			
				|  | @@ -15,40 +16,26 @@ extern "C"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include <stdio.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -///现在我们需要做的是让SaveFrame函数能把RGB信息定稿到一个PPM格式的文件中。
 | 
	
		
			
				|  |  | -///我们将生成一个简单的PPM格式文件,请相信,它是可以工作的。
 | 
	
		
			
				|  |  | -void SaveFrame(AVFrame *pFrame, int width, int height,int index)
 | 
	
		
			
				|  |  | +VideoPlayer::VideoPlayer()
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  FILE *pFile;
 | 
	
		
			
				|  |  | -  char szFilename[32];
 | 
	
		
			
				|  |  | -  int  y;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Open file
 | 
	
		
			
				|  |  | -  sprintf(szFilename, "frame%d.ppm", index);
 | 
	
		
			
				|  |  | -  pFile=fopen(szFilename, "wb");
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if(pFile==NULL)
 | 
	
		
			
				|  |  | -    return;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // Write header
 | 
	
		
			
				|  |  | -  fprintf(pFile, "P6\n%d %d\n255\n", width, height);
 | 
	
		
			
				|  |  | +VideoPlayer::~VideoPlayer()
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // Write pixel data
 | 
	
		
			
				|  |  | -  for(y=0; y<height; y++)
 | 
	
		
			
				|  |  | -  {
 | 
	
		
			
				|  |  | -    fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // Close file
 | 
	
		
			
				|  |  | -  fclose(pFile);
 | 
	
		
			
				|  |  | +void VideoPlayer::startPlay()
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    ///调用 QThread 的start函数 将会自动执行下面的run函数 run函数是一个新的线程
 | 
	
		
			
				|  |  | +    this->start();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -int main(int argc, char *argv[])
 | 
	
		
			
				|  |  | +void VideoPlayer::run()
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    char *file_path = "E:\\in.mp4";
 | 
	
		
			
				|  |  | +    char *file_path = mFileName.toUtf8().data();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      AVFormatContext *pFormatCtx;
 | 
	
		
			
				|  |  |      AVCodecContext *pCodecCtx;
 | 
	
	
		
			
				|  | @@ -69,12 +56,12 @@ int main(int argc, char *argv[])
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (avformat_open_input(&pFormatCtx, file_path, NULL, NULL) != 0) {
 | 
	
		
			
				|  |  |          printf("can't open the file. \n");
 | 
	
		
			
				|  |  | -        return -1;
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
 | 
	
		
			
				|  |  |          printf("Could't find stream infomation.\n");
 | 
	
		
			
				|  |  | -        return -1;
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      videoStream = -1;
 | 
	
	
		
			
				|  | @@ -91,7 +78,7 @@ int main(int argc, char *argv[])
 | 
	
		
			
				|  |  |      ///如果videoStream为-1 说明没有找到视频流
 | 
	
		
			
				|  |  |      if (videoStream == -1) {
 | 
	
		
			
				|  |  |          printf("Didn't find a video stream.\n");
 | 
	
		
			
				|  |  | -        return -1;
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      ///查找解码器
 | 
	
	
		
			
				|  | @@ -100,26 +87,27 @@ int main(int argc, char *argv[])
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (pCodec == NULL) {
 | 
	
		
			
				|  |  |          printf("Codec not found.\n");
 | 
	
		
			
				|  |  | -        return -1;
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      ///打开解码器
 | 
	
		
			
				|  |  |      if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
 | 
	
		
			
				|  |  |          printf("Could not open codec.\n");
 | 
	
		
			
				|  |  | -        return -1;
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      pFrame = av_frame_alloc();
 | 
	
		
			
				|  |  |      pFrameRGB = av_frame_alloc();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    ///这里我们改成了 将解码后的YUV数据转换成RGB32
 | 
	
		
			
				|  |  |      img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
 | 
	
		
			
				|  |  |              pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
 | 
	
		
			
				|  |  | -            PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
 | 
	
		
			
				|  |  | +            PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    numBytes = avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,pCodecCtx->height);
 | 
	
		
			
				|  |  | +    numBytes = avpicture_get_size(PIX_FMT_RGB32, pCodecCtx->width,pCodecCtx->height);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
 | 
	
		
			
				|  |  | -    avpicture_fill((AVPicture *) pFrameRGB, out_buffer, PIX_FMT_RGB24,
 | 
	
		
			
				|  |  | +    avpicture_fill((AVPicture *) pFrameRGB, out_buffer, PIX_FMT_RGB32,
 | 
	
		
			
				|  |  |              pCodecCtx->width, pCodecCtx->height);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      int y_size = pCodecCtx->width * pCodecCtx->height;
 | 
	
	
		
			
				|  | @@ -129,8 +117,6 @@ int main(int argc, char *argv[])
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      av_dump_format(pFormatCtx, 0, file_path, 0); //输出视频信息
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    int index = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      while (1)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |          if (av_read_frame(pFormatCtx, packet) < 0)
 | 
	
	
		
			
				|  | @@ -143,7 +129,7 @@ int main(int argc, char *argv[])
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              if (ret < 0) {
 | 
	
		
			
				|  |  |                  printf("decode error.\n");
 | 
	
		
			
				|  |  | -                return -1;
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              if (got_picture) {
 | 
	
	
		
			
				|  | @@ -152,17 +138,18 @@ int main(int argc, char *argv[])
 | 
	
		
			
				|  |  |                          pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data,
 | 
	
		
			
				|  |  |                          pFrameRGB->linesize);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                SaveFrame(pFrameRGB, pCodecCtx->width,pCodecCtx->height,index++); //保存图片
 | 
	
		
			
				|  |  | -                if (index > 50) return 0; //这里我们就保存50张图片
 | 
	
		
			
				|  |  | +                //把这个RGB数据 用QImage加载
 | 
	
		
			
				|  |  | +                QImage tmpImg((uchar *)out_buffer,pCodecCtx->width,pCodecCtx->height,QImage::Format_RGB32);
 | 
	
		
			
				|  |  | +                QImage image = tmpImg.copy(); //把图像复制一份 传递给界面显示
 | 
	
		
			
				|  |  | +                emit sig_GetOneFrame(image);  //发送信号
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          av_free_packet(packet);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        msleep(5); //停一停  不然放的太快了
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      av_free(out_buffer);
 | 
	
		
			
				|  |  |      av_free(pFrameRGB);
 | 
	
		
			
				|  |  |      avcodec_close(pCodecCtx);
 | 
	
		
			
				|  |  |      avformat_close_input(&pFormatCtx);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -
 |