1,451
社区成员
发帖
与我相关
我的任务
分享
//SDL线程
int sfp_refresh_thread(void *opaque)
{
while (thread_exit==0)
{
SDL_Event event;
event.type = SFM_REFRESH_EVENT;
SDL_PushEvent(&event);
}
//Quit
SDL_Event event;
event.type = SFM_BREAK_EVENT;
SDL_PushEvent(&event);
return 0;
}
//视频播放函数
int simplest_ffmpeg_player(LPVOID lpParam)
{
int i, videoindex;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame,*pFrameYUV;
uint8_t *out_buffer;
AVPacket packet;
int ret, got_picture;
//------------SDL----------------
int screen_w,screen_h;
SDL_Window *screen;
SDL_Renderer* sdlRenderer;
SDL_Texture* sdlTexture;
SDL_Rect sdlRect;
SDL_Thread *video_tid;
SDL_Event event;
struct SwsContext *img_convert_ctx;
CRTSPPlayerDlg *dlg=(CRTSPPlayerDlg *)lpParam;
static AVInputFormat *file_iformat;
AVFormatContext *ic = NULL;
AVDictionary **opts;
AVDictionaryEntry *t;
av_register_all();
avformat_network_init();
AVCodec *pACodec = avcodec_find_decoder(AV_CODEC_ID_H264);
pCodecCtx = NULL;
pCodecCtx = avcodec_alloc_context3(pACodec);
pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
pCodecCtx->width = 1920;
pCodecCtx->height = 1080;
if (avcodec_open2(pCodecCtx, pACodec, NULL) < 0)
{
AfxMessageBox("Could not open codec.\n");
return -1;
}
pFrame=av_frame_alloc();
pFrameYUV=av_frame_alloc();
out_buffer=(uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));
avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER))
{
AfxMessageBox( "Could not initialize SDL\n");
return -1;
}
//SDL 2.0 Support for multiple windows
screen_w = pCodecCtx->width;
screen_h = pCodecCtx->height;
//===========================================
//显示在MFC控件上
screen = SDL_CreateWindowFrom(dlg->GetDlgItem(IDC_SCREEN)->GetSafeHwnd());
//===========================================
if(!screen)
{
AfxMessageBox("SDL: could not create window - exiting\n");
return -1;
}
sdlRenderer = SDL_CreateRenderer(screen, -1, 0);
//IYUV: Y + U + V (3 planes)
//YV12: Y + V + U (3 planes)
sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING,pCodecCtx->width,pCodecCtx->height);
sdlRect.x=0;
sdlRect.y=0;
sdlRect.w=screen_w;
sdlRect.h=screen_h;
video_tid = SDL_CreateThread(sfp_refresh_thread,NULL,NULL);
//------------SDL End------------
//Event Loop
av_init_packet(&packet);
char dateBuf[DUMMY_SINK_RECEIVE_BUFFER_SIZE] = "";
for (;;)
{
//Wait
SDL_WaitEvent(&event);
if(event.type==SFM_REFRESH_EVENT)
{
//------------------------------
memset(dateBuf, 0, sizeof(dateBuf));
int len = dlg->read(dateBuf, 1);
if (len == 0)
{
if (thread_exit == 1)
{
break;
}
Sleep(20);
continue;
}
packet.data = (uint8_t *)dateBuf;
packet.size = len;
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &packet);
if(ret < 0)
{
continue;
AfxMessageBox("Decode Error.\n");
return -1;
}
if(got_picture)
{
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
SDL_UpdateTexture( sdlTexture, NULL, pFrameYUV->data[0], pFrameYUV->linesize[0] );
SDL_RenderClear( sdlRenderer );
SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, NULL);
SDL_RenderPresent( sdlRenderer );
}
av_free_packet(&packet);
}
else if(event.type==SDL_QUIT)
{
thread_exit=1;
}
else if(event.type==SFM_BREAK_EVENT)
{
break;
}
}
sws_freeContext(img_convert_ctx);
SDL_DestroyWindow(screen); //此函数会阻塞
SDL_DestroyRenderer(sdlRenderer);
SDL_DestroyTexture(sdlTexture);
SDL_Quit(); //此函数会阻塞
dlg->GetDlgItem(IDC_SCREEN)->ShowWindow(SW_SHOWNORMAL);
av_free(out_buffer);
av_frame_free(&pFrameYUV);
av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
return 0;
}
//播放线程
UINT Thread_Play(LPVOID lpParam){
simplest_ffmpeg_player(lpParam);
return 0;
}
//开启播放
void CRTSPPlayerDlg::OnBnClickedButtonPlay()
{
// TODO: 在此添加控件通知处理程序代码
m_ThreadHandleRetVal = CreateThread(NULL, 0, LPTHREAD_START_ROUTINE)Thread_Play, this, 0, NULL);
}
//停止播放
void CRTSPPlayerDlg::OnBnClickedButtonStop()
{
// TODO: 在此添加控件通知处理程序代码
thread_exit = 1;
m_pRtsp->stopRTSPClient();
WaitForSingleObject(m_ThreadHandleRetVal, INFINITE);//等待播放线程结束
.
.
.
.
}