|
@@ -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);
|