ffmpeg+sdl 播放器最新代码Word文件下载.docx
《ffmpeg+sdl 播放器最新代码Word文件下载.docx》由会员分享,可在线阅读,更多相关《ffmpeg+sdl 播放器最新代码Word文件下载.docx(24页珍藏版)》请在冰豆网上搜索。
![ffmpeg+sdl 播放器最新代码Word文件下载.docx](https://file1.bdocx.com/fileroot1/2023-1/22/e4b2fb33-33d8-46e0-957b-c75062972c71/e4b2fb33-33d8-46e0-957b-c75062972c711.gif)
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();
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)
pkt1->
pkt=*pkt;
next=NULL;
SDL_LockMutex(q->
mutex);
q->
last_pkt)
first_pkt=pkt1;
else
last_pkt->
next=pkt1;
last_pkt=pkt1;
nb_packets++;
size+=pkt1->
pkt.size;
SDL_CondSignal(q->
cond);
SDL_UnlockMutex(q->
return0;
staticintpacket_queue_get(PacketQueue*q,AVPacket*pkt,intblock)
intret;
for(;
;
)
if(global_video_state->
quit)
ret=-1;
break;
pkt1=q->
first_pkt;
if(pkt1)
first_pkt=pkt1->
next;
first_pkt)
last_pkt=NULL;
nb_packets--;
size-=pkt1->
*pkt=pkt1->
pkt;
av_free(pkt1);
ret=1;
elseif(!
block)
ret=0;
SDL_CondWait(q->
cond,q->
returnret;
intaudio_decode_frame(VideoState*is,uint8_t*audio_buf,intbuf_size)
intlen1,data_size;
AVPacket*pkt=&
is->
audio_pkt;
while(is->
audio_pkt_size>
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<
audio_pkt_size=0;
audio_pkt_data+=len1;
audio_pkt_size-=len1;
if(data_size<
=0)
continue;
returndata_size;
if(pkt->
data)
av_free_packet(pkt);
if(is->
if(packet_queue_get(&
audioq,pkt,1)<
audio_pkt_data=pkt->
data;
audio_pkt_size=pkt->
size;
voidaudio_callback(void*userdata,Uint8*stream,intlen)
VideoState*is=(VideoState*)userdata;
intlen1,audio_size;
while(len>
audio_buf_index>
=is->
audio_buf_size)
audio_size=audio_decode_frame(is,is->
audio_buf,sizeof(is->
audio_buf));
if(audio_size<
audio_buf_size=1024;
memset(is->
audio_buf,0,is->
audio_buf_size);
audio_buf_size=audio_size;
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;
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事件
staticvoidschedule_refresh(VideoState*is,intdelay)
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)
video_displaycalled\n"
);
SDL_Rectrect;
VideoPicture*vp;
AVPicturepict;
floataspect_ratio;
intw,h,x,y;
inti;
vp=&
pictq[is->
pictq_rindex];
if(vp->
bmp)
video_st->
codec->
sample_aspect_ratio.num==0)
aspect_ratio=0;
aspect_ratio=av_q2d(is->
sample_aspect_ratio)*
width/is->
height;
if(aspect_ratio<
=0.0)//aspect_ratio宽高比
aspect_ratio=(float)is->
width/
(float)is->
h=screen->
h;
w=((int)(h*aspect_ratio))&
-3;
if(w>
screen->
w)
w=screen->
w;
h=((int)(w/aspect_ratio))&
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)
video_st)
pictq_size==0)
schedule_refresh(is,1);
schedule_refresh(is,80);
video_display(is);
if(++is->
pictq_rindex==VIDEO_PICTURE_QUEUE_SIZE)
pictq_rindex=0;
SDL_LockMutex(is->
pictq_mutex);
pictq_size--;
SDL_CondSignal(is->
pictq_cond);
SDL_UnlockMutex(is->
schedule_refresh(is,100);
voidalloc_picture(void*userdata)
pictq_windex];
//wealreadyhaveonemakeanother,bigger/smaller
SDL_FreeYUVOverlay(vp->
bmp);
//AllocateaplacetoputourYUVimageonthatscreen
vp->
bmp=SDL_CreateYUVOverlay(is->
width,
height,
SDL_YV12_OVERLAY,
screen);
width=is->
width;
height=is->
allocated=1;
intqueue_picture(VideoState*is,AVFrame*pFrame)
queue_picturecalled\n"
intdst_pix_fmt;
staticstructSwsContext*img_convert_ctx;
if(img_convert_ctx==NULL)
img_convert_ctx=sws_getContext(is->
width,is->
pix_fmt,
PIX_FMT_YUV420P,
sws_flags,NULL,NULL,NULL);
fprintf(stderr,"
Cannotinitializetheconversioncontext\n"
exit
(1);
pictq_size>
=VIDEO_PICTURE_QUEUE_SIZE&
&
!
SDL_CondWait(is->
pictq_cond,is->
//windexissetto0initially
if(!
vp->
bmp||
width!
width||
height!
height)
allocated=0;
event.type=FF_ALLOC_EVENT;
event.user.data1=is;
while(!
allocated&
//没有得到消息时解锁,得到消息后加锁,和SDL_CondSignal配对使用
SDL_LockYUVOverlay(vp->
dst_pix_fmt=PIX_FMT_YUV420P;
pict.data[0]=vp->
bmp->
pixels[0];
pict.data[1]=vp->
pixels[2];
pict.data[2]=vp->
pixels[1];
pict.linesize[0]=vp->
pitches[0];
pict.linesize[1]=vp->
pitches[2];
pict.linesize[2]=vp->
pitches[1];
//ConverttheimageintoYUVformatthatSDLuses
sws_scale(img_convert_ctx,pFrame->
data,pFrame->
linesize,
0,is->
height,pict.data,pict.linesize);
SDL_UnlockYUVOverlay(vp->
pictq_windex==VIDEO_PICTURE_QUEUE_SIZE)
pictq_windex=0;
pictq_size++;
intvideo_thread(void*arg)
video_threadcalled"
VideoState*is=(VideoState*)arg;
AVPacketpkt1,*packet=&
pkt1;
intlen1,frameFinished;
AVFrame*pFrame;
pFrame=avcodec_alloc_frame();
videoq,packet,1)<
//meanswequitgettingpackets
//Decodevideoframe
len1=avcodec_decode_video(is->
codec,pFrame,&
frameFinished,
packet->
data,packet->
size);
//Didwegetavideof