ffmpeg+sdl 播放器最新代码.docx
- 文档编号:7655467
- 上传时间:2023-01-25
- 格式:DOCX
- 页数:24
- 大小:21.55KB
ffmpeg+sdl 播放器最新代码.docx
《ffmpeg+sdl 播放器最新代码.docx》由会员分享,可在线阅读,更多相关《ffmpeg+sdl 播放器最新代码.docx(24页珍藏版)》请在冰豆网上搜索。
ffmpeg+sdl播放器最新代码
#include"libavformat/avformat.h"
#include"libswscale/swscale.h"
//#include
#include
#include
#include
#include
#include
#include
#ifdefmain
#undefmain
#endif
#defineSDL_AUDIO_BUFFER_SIZE1024
#defineMAX_AUDIOQ_SIZE(5*16*1024)
#defineMAX_VIDEOQ_SIZE(5*256*1024)
#defineFF_ALLOC_EVENT(SDL_USEREVENT)
#defineFF_REFRESH_EVENT(SDL_USEREVENT+1)
#defineFF_QUIT_EVENT(SDL_USEREVENT+2)
#defineVIDEO_PICTURE_QUEUE_SIZE1
#defineSDL_AUDIO_BUFFER_SIZE1024
staticintsws_flags=SWS_BICUBIC;
typedefstructPacketQueue
{
AVPacketList*first_pkt,*last_pkt;
intnb_packets;
intsize;
SDL_mutex*mutex;
SDL_cond*cond;
}PacketQueue;
typedefstructVideoPicture
{
SDL_Overlay*bmp;
intwidth,height;
intallocated;
}VideoPicture;
typedefstructVideoState
{
AVFormatContext*pFormatCtx;
intvideoStream,audioStream;
AVStream*audio_st;
PacketQueueaudioq;
uint8_taudio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE*3)/2];
unsignedintaudio_buf_size;
unsignedintaudio_buf_index;
AVPacketaudio_pkt;
uint8_t*audio_pkt_data;
intaudio_pkt_size;
AVStream*video_st;
PacketQueuevideoq;
VideoPicturepictq[VIDEO_PICTURE_QUEUE_SIZE];
intpictq_size,pictq_rindex,pictq_windex;
SDL_mutex*pictq_mutex;
SDL_cond*pictq_cond;
SDL_Thread*parse_tid;
SDL_Thread*video_tid;
charfilename[1024];
intquit;
}VideoState;
SDL_Surface*screen;
VideoState*global_video_state;
voidpacket_queue_init(PacketQueue*q)
{
memset(q,0,sizeof(PacketQueue));
q->mutex=SDL_CreateMutex();
q->cond=SDL_CreateCond();
}
intpacket_queue_put(PacketQueue*q,AVPacket*pkt)
{
AVPacketList*pkt1;
if(av_dup_packet(pkt)<0)
{
return-1;
}
pkt1=(AVPacketList*)av_malloc(sizeof(AVPacketList));
if(!
pkt1)
return-1;
pkt1->pkt=*pkt;
pkt1->next=NULL;
SDL_LockMutex(q->mutex);
if(!
q->last_pkt)
q->first_pkt=pkt1;
else
q->last_pkt->next=pkt1;
q->last_pkt=pkt1;
q->nb_packets++;
q->size+=pkt1->pkt.size;
SDL_CondSignal(q->cond);
SDL_UnlockMutex(q->mutex);
return0;
}
staticintpacket_queue_get(PacketQueue*q,AVPacket*pkt,intblock)
{
AVPacketList*pkt1;
intret;
SDL_LockMutex(q->mutex);
for(;;)
{
if(global_video_state->quit)
{
ret=-1;
break;
}
pkt1=q->first_pkt;
if(pkt1)
{
q->first_pkt=pkt1->next;
if(!
q->first_pkt)
q->last_pkt=NULL;
q->nb_packets--;
q->size-=pkt1->pkt.size;
*pkt=pkt1->pkt;
av_free(pkt1);
ret=1;
break;
}
elseif(!
block)
{
ret=0;
break;
}
else
{
SDL_CondWait(q->cond,q->mutex);
}
}
SDL_UnlockMutex(q->mutex);
returnret;
}
intaudio_decode_frame(VideoState*is,uint8_t*audio_buf,intbuf_size)
{
intlen1,data_size;
AVPacket*pkt=&is->audio_pkt;
for(;;)
{
while(is->audio_pkt_size>0)
{
data_size=buf_size;
len1=avcodec_decode_audio2(is->audio_st->codec,
(int16_t*)audio_buf,&data_size,
is->audio_pkt_data,is->audio_pkt_size);
if(len1<0)
{
is->audio_pkt_size=0;
break;
}
is->audio_pkt_data+=len1;
is->audio_pkt_size-=len1;
if(data_size<=0)
{
continue;
}
returndata_size;
}
if(pkt->data)
av_free_packet(pkt);
if(is->quit)
{
return-1;
}
if(packet_queue_get(&is->audioq,pkt,1)<0)
{
return-1;
}
is->audio_pkt_data=pkt->data;
is->audio_pkt_size=pkt->size;
}
}
voidaudio_callback(void*userdata,Uint8*stream,intlen)
{
VideoState*is=(VideoState*)userdata;
intlen1,audio_size;
while(len>0)
{
if(is->audio_buf_index>=is->audio_buf_size)
{
audio_size=audio_decode_frame(is,is->audio_buf,sizeof(is->audio_buf));
if(audio_size<0)
{
is->audio_buf_size=1024;
memset(is->audio_buf,0,is->audio_buf_size);
}
else
{
is->audio_buf_size=audio_size;
}
is->audio_buf_index=0;
}
len1=is->audio_buf_size-is->audio_buf_index;
if(len1>len)
len1=len;
memcpy(stream,(uint8_t*)is->audio_buf+is->audio_buf_index,len1);
len-=len1;
stream+=len1;
is->audio_buf_index+=len1;
}
}
staticUint32sdl_refresh_timer_cb(Uint32interval,void*opaque)
{
//printf("sdl_refresh_timer_cbcalled:
interval--%d\n",interval);
SDL_Eventevent;
event.type=FF_REFRESH_EVENT;
event.user.data1=opaque;
SDL_PushEvent(&event);//派发FF_REFRESH_EVENT事件
return0;
}
staticvoidschedule_refresh(VideoState*is,intdelay)
{
//printf("schedule_refreshcalled:
delay--%d\n",delay);
SDL_AddTimer(delay,sdl_refresh_timer_cb,is);//sdl_refresh_timer_cb函数在延时delay毫秒后,只会被执行一次,is是sdl_refresh_timer_cb的参数
}
voidvideo_display(VideoState*is)
{
//printf("video_displaycalled\n");
SDL_Rectrect;
VideoPicture*vp;
AVPicturepict;
floataspect_ratio;
intw,h,x,y;
inti;
vp=&is->pictq[is->pictq_rindex];
if(vp->bmp)
{
if(is->video_st->codec->sample_aspect_ratio.num==0)
{
aspect_ratio=0;
}
else
{
aspect_ratio=av_q2d(is->video_st->codec->sample_aspect_ratio)*
is->video_st->codec->width/is->video_st->codec->height;
}
if(aspect_ratio<=0.0)//aspect_ratio宽高比
{
aspect_ratio=(float)is->video_st->codec->width/
(float)is->video_st->codec->height;
}
h=screen->h;
w=((int)(h*aspect_ratio))&-3;
if(w>screen->w)
{
w=screen->w;
h=((int)(w/aspect_ratio))&-3;
}
x=(screen->w-w)/2;
y=(screen->h-h)/2;
rect.x=x;
rect.y=y;
rect.w=w;
rect.h=h;
SDL_DisplayYUVOverlay(vp->bmp,&rect);
}
}
voidvideo_refresh_timer(void*userdata)
{
VideoState*is=(VideoState*)userdata;
VideoPicture*vp;
if(is->video_st)
{
if(is->pictq_size==0)
{
schedule_refresh(is,1);
}
else
{
vp=&is->pictq[is->pictq_rindex];
schedule_refresh(is,80);
video_display(is);
if(++is->pictq_rindex==VIDEO_PICTURE_QUEUE_SIZE)
{
is->pictq_rindex=0;
}
SDL_LockMutex(is->pictq_mutex);
is->pictq_size--;
SDL_CondSignal(is->pictq_cond);
SDL_UnlockMutex(is->pictq_mutex);
}
}
else
{
schedule_refresh(is,100);
}
}
voidalloc_picture(void*userdata)
{
VideoState*is=(VideoState*)userdata;
VideoPicture*vp;
vp=&is->pictq[is->pictq_windex];
if(vp->bmp)
{
//wealreadyhaveonemakeanother,bigger/smaller
SDL_FreeYUVOverlay(vp->bmp);
}
//AllocateaplacetoputourYUVimageonthatscreen
vp->bmp=SDL_CreateYUVOverlay(is->video_st->codec->width,
is->video_st->codec->height,
SDL_YV12_OVERLAY,
screen);
vp->width=is->video_st->codec->width;
vp->height=is->video_st->codec->height;
SDL_LockMutex(is->pictq_mutex);
vp->allocated=1;
SDL_CondSignal(is->pictq_cond);
SDL_UnlockMutex(is->pictq_mutex);
}
intqueue_picture(VideoState*is,AVFrame*pFrame)
{
//printf("queue_picturecalled\n");
VideoPicture*vp;
intdst_pix_fmt;
AVPicturepict;
staticstructSwsContext*img_convert_ctx;
if(img_convert_ctx==NULL)
{
img_convert_ctx=sws_getContext(is->video_st->codec->width,is->video_st->codec->height,
is->video_st->codec->pix_fmt,
is->video_st->codec->width,is->video_st->codec->height,
PIX_FMT_YUV420P,
sws_flags,NULL,NULL,NULL);
if(img_convert_ctx==NULL)
{
fprintf(stderr,"Cannotinitializetheconversioncontext\n");
exit
(1);
}
}
SDL_LockMutex(is->pictq_mutex);
while(is->pictq_size>=VIDEO_PICTURE_QUEUE_SIZE&&
!
is->quit)
{
SDL_CondWait(is->pictq_cond,is->pictq_mutex);
}
SDL_UnlockMutex(is->pictq_mutex);
if(is->quit)
return-1;
//windexissetto0initially
vp=&is->pictq[is->pictq_windex];
if(!
vp->bmp||
vp->width!
=is->video_st->codec->width||
vp->height!
=is->video_st->codec->height)
{
SDL_Eventevent;
vp->allocated=0;
event.type=FF_ALLOC_EVENT;
event.user.data1=is;
SDL_PushEvent(&event);
SDL_LockMutex(is->pictq_mutex);
while(!
vp->allocated&&!
is->quit)
{
SDL_CondWait(is->pictq_cond,is->pictq_mutex);//没有得到消息时解锁,得到消息后加锁,和SDL_CondSignal配对使用
}
SDL_UnlockMutex(is->pictq_mutex);
if(is->quit)
{
return-1;
}
}
if(vp->bmp)
{
SDL_LockYUVOverlay(vp->bmp);
dst_pix_fmt=PIX_FMT_YUV420P;
pict.data[0]=vp->bmp->pixels[0];
pict.data[1]=vp->bmp->pixels[2];
pict.data[2]=vp->bmp->pixels[1];
pict.linesize[0]=vp->bmp->pitches[0];
pict.linesize[1]=vp->bmp->pitches[2];
pict.linesize[2]=vp->bmp->pitches[1];
//ConverttheimageintoYUVformatthatSDLuses
sws_scale(img_convert_ctx,pFrame->data,pFrame->linesize,
0,is->video_st->codec->height,pict.data,pict.linesize);
SDL_UnlockYUVOverlay(vp->bmp);
if(++is->pictq_windex==VIDEO_PICTURE_QUEUE_SIZE)
{
is->pictq_windex=0;
}
SDL_LockMutex(is->pictq_mutex);
is->pictq_size++;
SDL_UnlockMutex(is->pictq_mutex);
}
return0;
}
intvideo_thread(void*arg)
{
//printf("video_threadcalled");
VideoState*is=(VideoState*)arg;
AVPacketpkt1,*packet=&pkt1;
intlen1,frameFinished;
AVFrame*pFrame;
pFrame=avcodec_alloc_frame();
for(;;)
{
if(packet_queue_get(&is->videoq,packet,1)<0)
{
//meanswequitgettingpackets
break;
}
//Decodevideoframe
len1=avcodec_decode_video(is->video_st->codec,pFrame,&frameFinished,
packet->data,packet->size);
//Didwegetavideof
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ffmpeg+sdl 播放器最新代码 ffmpeg sdl 播放 最新 代码
![提示](https://static.bdocx.com/images/bang_tan.gif)