|  | @@ -1,6 +1,6 @@
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * Ò¶º£»Ô
 | 
	
		
			
				|  |  | - * QQȺ121376426
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * �海辉
 | 
	
		
			
				|  |  | + * QQ群121376426
 | 
	
		
			
				|  |  |   * http://blog.yundiantech.com/
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -15,16 +15,16 @@ void VideoPlayer::decodeVideoThread()
 | 
	
		
			
				|  |  |      int videoWidth  = 0;
 | 
	
		
			
				|  |  |      int videoHeight =  0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    double video_pts = 0; //µ±Ç°ÊÓÆµµÄpts
 | 
	
		
			
				|  |  | -    double audio_pts = 0; //񙮵pts
 | 
	
		
			
				|  |  | +    double video_pts = 0; //当�视频的pts
 | 
	
		
			
				|  |  | +    double audio_pts = 0; //音频pts
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    ///½âÂëÊÓÆµÏà¹Ø
 | 
	
		
			
				|  |  | +    ///解�视频相关
 | 
	
		
			
				|  |  |      AVFrame *pFrame = nullptr;
 | 
	
		
			
				|  |  |      AVFrame *pFrameYUV = nullptr;
 | 
	
		
			
				|  |  | -    uint8_t *yuv420pBuffer = nullptr; //½âÂëºóµÄyuvÊý¾Ý
 | 
	
		
			
				|  |  | -    struct SwsContext *imgConvertCtx = nullptr;  //ÓÃÓÚ½âÂëºóµÄÊÓÆµ¸ñʽת»»
 | 
	
		
			
				|  |  | +    uint8_t *yuv420pBuffer = nullptr; //解��的yuv数�
 | 
	
		
			
				|  |  | +    struct SwsContext *imgConvertCtx = nullptr;  //用于解��的视频格�转�
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    AVCodecContext *pCodecCtx = mVideoStream->codec; //ÊÓÆµ½âÂëÆ÷
 | 
	
		
			
				|  |  | +    AVCodecContext *pCodecCtx = mVideoStream->codec; //视频解�器
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      pFrame = av_frame_alloc();
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -32,11 +32,11 @@ void VideoPlayer::decodeVideoThread()
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |          if (mIsQuit)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            clearVideoQuene(); //Çå¿Õ¶ÓÁÐ
 | 
	
		
			
				|  |  | +            clearVideoQuene(); //清空队列
 | 
	
		
			
				|  |  |              break;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        if (mIsPause == true) //ÅжÏÔÝÍ£
 | 
	
		
			
				|  |  | +        if (mIsPause == true) //åˆ¤æ–æš‚å�œ
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              mSleep(10);
 | 
	
		
			
				|  |  |              continue;
 | 
	
	
		
			
				|  | @@ -49,12 +49,12 @@ void VideoPlayer::decodeVideoThread()
 | 
	
		
			
				|  |  |              mConditon_Video->Unlock();
 | 
	
		
			
				|  |  |              if (mIsReadFinished)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                //¶ÓÁÐÀïÃæÃ»ÓÐÊý¾ÝÁËÇÒ¶ÁÈ¡Íê±ÏÁË
 | 
	
		
			
				|  |  | +                //队列里�没有数�了且读�完毕了
 | 
	
		
			
				|  |  |                  break;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              else
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                mSleep(1); //¶ÓÁÐÖ»ÊÇÔÝʱûÓÐÊý¾Ý¶øÒÑ
 | 
	
		
			
				|  |  | +                mSleep(1); //队列�是暂时没有数�而已
 | 
	
		
			
				|  |  |                  continue;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -66,7 +66,7 @@ void VideoPlayer::decodeVideoThread()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          AVPacket *packet = &pkt1;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        //ÊÕµ½Õâ¸öÊý¾Ý ˵Ã÷¸Õ¸ÕÖ´ÐйýÌø×ª ÏÖÔÚÐèÒª°Ñ½âÂëÆ÷µÄÊý¾Ý Çå³ýÒ»ÏÂ
 | 
	
		
			
				|  |  | +        //收到这个数� 说明刚刚执行过跳转 现在需�把解�器的数� 清除一下
 | 
	
		
			
				|  |  |          if(strcmp((char*)packet->data, FLUSH_DATA) == 0)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              avcodec_flush_buffers(mVideoStream->codec);
 | 
	
	
		
			
				|  | @@ -101,7 +101,7 @@ void VideoPlayer::decodeVideoThread()
 | 
	
		
			
				|  |  |      //OUTPUT("%s %f \n", __FUNCTION__, video_pts);
 | 
	
		
			
				|  |  |              if (seek_flag_video)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                //·¢ÉúÁËÌø×ª ÔòÌø¹ý¹Ø¼üÖ¡µ½Ä¿µÄʱ¼äµÄÕ⼸֡
 | 
	
		
			
				|  |  | +                //�生了跳转 则跳过关键帧到目的时间的这几帧
 | 
	
		
			
				|  |  |                 if (video_pts < seek_time)
 | 
	
		
			
				|  |  |                 {
 | 
	
		
			
				|  |  |                     av_packet_unref(packet);
 | 
	
	
		
			
				|  | @@ -113,7 +113,7 @@ void VideoPlayer::decodeVideoThread()
 | 
	
		
			
				|  |  |                 }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            ///ÒôÊÓÆµÍ¬²½£¬ÊµÏÖµÄÔÀí¾ÍÊÇ£¬ÅжÏÊÇ·ñµ½ÏÔʾ´Ë֡ͼÏñµÄʱ¼äÁË£¬Ã»µ½ÔòÐÝÃß5ms£¬È»ºó¼ÌÐøÅжÏ
 | 
	
		
			
				|  |  | +            ///音视频å�Œæ¥ï¼Œå®žçŽ°çš„åŽŸç�†å°±æ˜¯ï¼Œåˆ¤æ–是å�¦åˆ°æ˜¾ç¤ºæ¤å¸§å›¾åƒ�的时间了,没到则休眠5ms,然å�Žç»§ç»åˆ¤æ–
 | 
	
		
			
				|  |  |              while(1)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  if (mIsQuit)
 | 
	
	
		
			
				|  | @@ -124,25 +124,25 @@ void VideoPlayer::decodeVideoThread()
 | 
	
		
			
				|  |  |                  if (mAudioStream != NULL && !mIsAudioThreadFinished)
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  |                      if (mIsReadFinished && mAudioPacktList.size() <= 0)
 | 
	
		
			
				|  |  | -                    {//¶ÁÈ¡ÍêÁË ÇÒÒôƵÊý¾ÝÒ²²¥·ÅÍêÁË ¾ÍÊ£ÏÂÊÓÆµÊý¾ÝÁË  Ö±½ÓÏÔʾ³öÀ´ÁË ²»ÓÃͬ²½ÁË
 | 
	
		
			
				|  |  | +                    {//读å�–完了 且音频数æ�®ä¹Ÿæ’放完了 就剩下视频数æ�®äº†  直接显示出æ�¥äº† ä¸�用å�Œæ¥äº†
 | 
	
		
			
				|  |  |                          break;
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    ///ÓÐÒôƵµÄÇé¿öÏ£¬½«ÊÓÆµÍ¬²½µ½ÒôƵ
 | 
	
		
			
				|  |  | -                    ///¸úÒôƵµÄpts×ö¶Ô±È£¬±ÈÊÓÆµ¿ìÔò×öÑÓʱ
 | 
	
		
			
				|  |  | +                    ///有音频的情况下,将视频å�Œæ¥åˆ°éŸ³é¢‘
 | 
	
		
			
				|  |  | +                    ///跟音频的pts�对比,比视频快则�延时
 | 
	
		
			
				|  |  |                      audio_pts = audio_clock;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |                  else
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  | -                    ///ûÓÐÒôƵµÄÇé¿öÏ£¬Ö±½Óͬ²½µ½ÍⲿʱÖÓ
 | 
	
		
			
				|  |  | +                    ///没有音频的情况下,直接å�Œæ¥åˆ°å¤–部时钟
 | 
	
		
			
				|  |  |                      audio_pts = (av_gettime() - mVideoStartTime) / 1000000.0;
 | 
	
		
			
				|  |  |                      audio_clock = audio_pts;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      //OUTPUT("%s %f %f \n", __FUNCTION__, video_pts, audio_pts);
 | 
	
		
			
				|  |  | -                //Ö÷ÒªÊÇ Ìø×ªµÄʱºò ÎÒÃǰÑvideo_clockÉèÖóÉ0ÁË
 | 
	
		
			
				|  |  | -                //Òò´ËÕâÀïÐèÒª¸üÐÂvideo_pts
 | 
	
		
			
				|  |  | -                //·ñÔòµ±´ÓºóÃæÌø×ªµ½Ç°ÃæµÄʱºò »á¿¨ÔÚÕâÀï
 | 
	
		
			
				|  |  | +                //主�是 跳转的时候 我们把video_clock设置�0了
 | 
	
		
			
				|  |  | +                //å› æ¤è¿™é‡Œéœ€è¦�æ›´æ–°video_pts
 | 
	
		
			
				|  |  | +                //�则当从��跳转到��的时候 会�在这里
 | 
	
		
			
				|  |  |                  video_pts = video_clock;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  if (video_pts <= audio_pts) break;
 | 
	
	
		
			
				|  | @@ -179,15 +179,15 @@ void VideoPlayer::decodeVideoThread()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  pFrameYUV = av_frame_alloc();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                int yuvSize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1);  //°´1×Ö½Ú½øÐÐÄÚ´æ¶ÔÆë,µÃµ½µÄÄÚ´æ´óС×î½Ó½üʵ¼Ê´óС
 | 
	
		
			
				|  |  | -            //    int yuvSize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 0);  //°´0×Ö½Ú½øÐÐÄÚ´æ¶ÔÆë£¬µÃµ½µÄÄÚ´æ´óСÊÇ0
 | 
	
		
			
				|  |  | -            //    int yuvSize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 4);   //°´4×Ö½Ú½øÐÐÄÚ´æ¶ÔÆë£¬µÃµ½µÄÄÚ´æ´óСÉÔ΢´óһЩ
 | 
	
		
			
				|  |  | +                int yuvSize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1);  //按1å—节进行内å˜å¯¹é½�,得到的内å˜å¤§å°�最接近实际大å°�
 | 
	
		
			
				|  |  | +            //    int yuvSize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 0);  //按0å—节进行内å˜å¯¹é½�,得到的内å˜å¤§å°�是0
 | 
	
		
			
				|  |  | +            //    int yuvSize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 4);   //按4å—节进行内å˜å¯¹é½�,得到的内å˜å¤§å°�ç¨�微大一些
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  unsigned int numBytes = static_cast<unsigned int>(yuvSize);
 | 
	
		
			
				|  |  |                  yuv420pBuffer = static_cast<uint8_t *>(av_malloc(numBytes * sizeof(uint8_t)));
 | 
	
		
			
				|  |  |                  av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, yuv420pBuffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                ///ÓÉÓÚ½âÂëºóµÄÊý¾Ý²»Ò»¶¨¶¼ÊÇyuv420p£¬Òò´ËÐèÒª½«½âÂëºóµÄÊý¾Ýͳһת»»³ÉYUV420P
 | 
	
		
			
				|  |  | +                ///由于解ç �å�Žçš„æ•°æ�®ä¸�一定都是yuv420p,因æ¤éœ€è¦�将解ç �å�Žçš„æ•°æ�®ç»Ÿä¸€è½¬æ�¢æˆ�YUV420P
 | 
	
		
			
				|  |  |                  imgConvertCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
 | 
	
		
			
				|  |  |                          pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
 | 
	
		
			
				|  |  |                          AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
 |