#include <stdlib.h>
#include <stdio.h>
#include <glib/gprintf.h>
#include <fcntl.h>
#include <gtk/gtk.h>
#include <SDL/SDL.h>
#include <pthread.h>
#include <gdk/gdkx.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
char SDL_windowhack[32];
GtkWidget* MainWindow;
void * PlayFileThread (void * data);
typedef struct VideoState{
char szFileName[1024];
int iFPS;//帧率
int iSpeed;//速度
int iPlayState;//播放状态
int iFileSize;
FILE *PlayFileCtrl ;
GtkWidget* PlayScreen;//绘图区
SDL_Surface* pSDLScreen ; //SDL surface
SDL_Overlay* pYUVoverlay ; // YUV
SDL_Rect strPlayArea; //绘图区大小
pthread_t PlayThread; //播放线程
SDL_mutex* pMutex; //操作锁
}VideoControl,*PVideoControl;
VideoControl strPlayControl;
int InitialSDL();
void FileOpen( GtkWidget* widget, gpointer data )
{
const gchar* strFileNameTmp = NULL;
GtkWidget* SelectFile = NULL;
if( strPlayControl.iPlayState > -1)
{
strPlayControl.iPlayState = -1;
}
SelectFile = gtk_file_selection_new("YUV File");
if(gtk_dialog_run(GTK_DIALOG(SelectFile)) == GTK_RESPONSE_OK)
{
///获得文件名
strFileNameTmp = gtk_file_selection_get_filename(
GTK_FILE_SELECTION(SelectFile)
);
if (strFileNameTmp == NULL)
{
gtk_widget_destroy(SelectFile);
return;
}
strcpy (strPlayControl.szFileName, strFileNameTmp);
printf("%s\n",strPlayControl.szFileName);
gtk_widget_destroy(SelectFile);
//打开文件
strPlayControl.PlayFileCtrl = fopen(
strPlayControl.szFileName,
"rb");
if (!strPlayControl.PlayFileCtrl)
{
fprintf(stderr,"open file error");
return;
}
fseek(strPlayControl.PlayFileCtrl, 0, SEEK_END);
strPlayControl.iFileSize = ftell(
strPlayControl.PlayFileCtrl
);
if( strPlayControl.iFileSize < 0)
{
printf("Fail to get file size");;
return;
}
fseek(strPlayControl.PlayFileCtrl, 0, SEEK_SET);
}
return;
}
void PlayFile( GtkWidget* widget, gpointer data )
{
int nRet;
if(strPlayControl.PlayFileCtrl == NULL)
{
return;
}
while( strPlayControl.iPlayState != -2)
{
if(strPlayControl.iPlayState == 1)
{
return;
}
if(strPlayControl.iPlayState == 0)
{
strPlayControl.iPlayState = 1;
return;
}
}
nRet = pthread_create( &strPlayControl.PlayThread,
NULL,
PlayFileThread,
(void*)(&strPlayControl)
);
if(nRet != 0)
{
fprintf(stderr, " Create play thread fail \n");
return;
}
strPlayControl.iPlayState = 1;
}
void * PlayFileThread (void * data)
{
VideoControl *PlayControl = (VideoControl *)data;
//文件操作指针
FILE *FileCtrl = PlayControl->PlayFileCtrl;
//首数据
fseek(FileCtrl,0,SEEK_SET);
//int FileSize = PlayControl->iFileSize;
//显示区
SDL_Overlay* YUVoverlay = NULL;
//绘图区
GtkWidget* ViewScreen =PlayControl->PlayScreen ;
//帧率
int iSpeed;
//分辨率
int Fpd = PlayControl->iFPS;
//帧大小
int FrameSize ;
//绘图区域
SDL_Rect ViewArea;
//数据快
char FrameData[608256];
int DataSize;
//绘图区域
ViewArea.x = 0;
ViewArea.y = 0;
//正的大小
switch(Fpd)
{
case 0: //QCIF
FrameSize =176*144*3/2;
ViewArea.w =176;
ViewArea.h = 144;
break;
case 1: //CIF
FrameSize = 352*288*3/2;
ViewArea.w = 352;
ViewArea.h = 288;
break;
case 2: //4CIF
FrameSize =704*576*3/2;
ViewArea.w = 704;
ViewArea.h = 576;
break;
}
// printf("%d\n",FrameSize);
YUVoverlay = SDL_CreateYUVOverlay( ViewArea.w,
ViewArea.h,
SDL_IYUV_OVERLAY,
strPlayControl.pSDLScreen
);
while(1)
{
//播放状态
if(PlayControl->iPlayState == 1)
{
//显示区的大小改变,重新setVideoMode
if( ViewArea.w != ViewScreen->allocation.width
|| ViewArea.h != ViewScreen->allocation.height)
{
ViewArea.w = ViewScreen->allocation.width;
ViewArea.h = ViewScreen->allocation.height;
PlayControl->pSDLScreen = SDL_SetVideoMode(
ViewArea.w,
ViewArea.h,
0,
SDL_SWSURFACE|SDL_NOFRAME);
}
//播放速率
iSpeed = (int)(1000/PlayControl->iSpeed);
//读取帧
DataSize = fread(FrameData,1, FrameSize, FileCtrl);
//printf("%d\n",DataSize);
if(DataSize == FrameSize)
{
//显示图像
SDL_LockSurface(PlayControl->pSDLScreen);
SDL_LockYUVOverlay(YUVoverlay);
memcpy(*(YUVoverlay->pixels),FrameData,FrameSize);
SDL_UnlockYUVOverlay(YUVoverlay);
SDL_UnlockSurface(PlayControl->pSDLScreen);
SDL_DisplayYUVOverlay(YUVoverlay, &ViewArea);
//控制帧率
SDL_Delay(iSpeed);
}
else
{
if(feof(FileCtrl))
{
printf("文件结束\n");
PlayControl->iPlayState = 0;
fseek(FileCtrl,0,0);
}
else
{
printf("文件读取错误\n");
PlayControl->iPlayState = -2;
break;
}
}
}
//非播放状态
else
{
//停止状态,退出
if(PlayControl->iPlayState == -1)
{
PlayControl->iPlayState = -2;
break;
}
//暂停状态,继续执行,等待他停止
}
}
fclose(FileCtrl);
strPlayControl.PlayFileCtrl = NULL;
SDL_FreeYUVOverlay(YUVoverlay);
return NULL;
}
void Pause( GtkWidget* widget, gpointer data )
{
if(strPlayControl.iPlayState == 1)
{
strPlayControl.iPlayState = 0;
}
}
void StopPlay( GtkWidget* widget, gpointer data )
{
strPlayControl.iPlayState = -1;
}
void ReplayFile( GtkWidget* widget, gpointer data )
{
if(strPlayControl.iPlayState >= 0)
{
strPlayControl.iPlayState = 1;
fseek(strPlayControl.PlayFileCtrl,0,SEEK_SET);
}
}
void PlaySlow( GtkWidget* widget, gpointer data )
{
if(strPlayControl.iSpeed > 5)
{
strPlayControl.iSpeed = (strPlayControl.iSpeed-5);
}
}
void PlayFast( GtkWidget* widget, gpointer data )
{
if(strPlayControl.iSpeed < 50)
{
strPlayControl.iSpeed = (strPlayControl.iSpeed+5);
}
}
void FullScreen( GtkWidget* widget, gpointer data )
{
gtk_window_fullscreen( GTK_WINDOW( MainWindow));
}
void SetPixel( GtkWidget* widget, gpointer data )
{
gchar* string;
string = gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget));
if (!strcasecmp(string, "QCIF"))
{
strPlayControl.iFPS = 0;
}
if (!strcasecmp(string, "CIF"))
{
strPlayControl.iFPS = 1;
}
if (!strcasecmp(string, "4CIF"))
{
strPlayControl.iFPS = 2;
}
return ;
}
gint delete_event( GtkWidget *widget, gpointer data )
{
/* 如果你的 "delete_event" 信号处理函数返回 FALSE,GTK 会发出 "destroy" 信号。
* 返回 TRUE,你不希望关闭窗口。
* 当你想弹出“你确定要退出吗?”对话框时它很有用。*/
if(strPlayControl.iPlayState != -2)
{
strPlayControl.iPlayState = -1 ;
}
while( strPlayControl.iPlayState != -2)
{
SDL_Delay(10);
}
SDL_Quit();
g_print ("delete event occurred\n");
/* 改 TRUE 为 FALSE 程序会关闭。*/
gtk_main_quit ();
return TRUE;
}
void InitialDrawArea(GtkWidget* PlayVideoArea)
{
gtk_
- 1
- 2
- 3
- 4
前往页