天天看點

基于QT的mplayer播放器

一、項目概述

Mplayer。它支援大量的多媒體檔案格式,像常見的音頻檔案如mp3/wav/mid,常見的視訊檔案如avi/vcd/dvd/rm等等,各種視訊編/解碼方式也是應有盡有。

我們項目的目标是在liunx下,用QT做一個MPlayer皮膚,能夠實作播放器的常見

功能,如:播放、停止、快進、快退、上/下一曲等。并把程式移植到ARM平台上。

二、功能體驗

本節主要目的是讓大家在學習具體實作過程前,先體驗下播放器的功能。

1、PC端功能體驗

将“項目代碼/工程代碼”目錄下的mplayer.tar.gz拷貝linux系統中(主機環境配置好以後,參照第四節的實作過程)。

#tar xvfz mplayer.tar.gz

#./mplayer

2、目标平台功能體驗

l         将“項目代碼/工程鏡像”檔案夾中的zImage、rootfs.cramfs燒寫到目标闆(或者采用nfs方式)。分區情況為:

Boot: 0 - 40000   size=0x40000

Kernel:40000 – 240000  size=0x200000

Rootfs: 240000 -3740000  size=0x3500000

啟動參數為:

setenv root=1f02 init=/linuxrc rootfstype=cramfs console=ttySAC0,115200 display=sam240

setenv bootcmd setenv bootcmd nand read 30008000 40000 200000 /; go 30008000

l         啟動系統後運作:

#. ./Qtopia.sh

#cd mymplayer

#./mymplayer -qws

三、實作原理

先來考慮考慮如何為mplayer編寫前端界面的問題。有兩種思路,一種是把mplayer解剖,直接修改他裡面的代碼,這樣我們做得界面就能夠和mplayer一體了(當然也能夠通過link mplayer用到的任何的庫和.o文檔,把他無縫的內建在程式裡面);第二種方法就是mplayer所謂的slave模式。

mplayer '/home/linux/1.mp3' -quiet -slave

現在來探讨一下slave模式:所謂的slave模式,就是mplayer在運作過程中能夠接收使用者的輸入指令行,具體支援哪些指令行,能夠通過mplayer -input cmdlist這條指令來得到,在Mplayer源碼的slave.txt中也有對這些指令有詳細的講解。Slave模式下工作的Mplayer可以和系統的标準輸入、輸出進行資訊互動。我們可以用linux C程式設計來完成對slave模式工作的Mplayer進行控制和資訊擷取。

如:

mkfifo(“/tmp/fifo”,0777);

可以使用popen()來打開Mplayer

FILE* mp;

mp=popen(“mplyer /home/linux/1.mp3 -quiet –slave –input file=/tmp/fifo,”r”);

可以通過管道/tmp/fifo給mplayer發送指令,通過mp擷取mplay的傳回資料

如:system(“echo /”mute 0/” > /tmp/fifo”);//寫指令

fgets(buf,1000,mp);//讀取mplay傳回資料

而Qt給我們提供了更友善的實作方法。

通過定義一個QProcess對象調用已編譯好的Mplayer。

QProcess *process = new QProcess();

process->setProcessChannelMode(QProcess::MergedChannels);

Process->start(“mplayer –ac mad xxxxx”);

在指令中添加 -slave 和 -quiet就可以通過指令設定Mplayer實作相應的功能。在mplayer源碼中的,slave.txt中對這些指令有詳細的講解。

Process->start(“mplayer –slave –quiet –ac mad xxxxx”);

1、暫停功能

通過如下代碼可以設定Mplayer暫停。

process->write(“pause/n”);

執行這段代碼的時候如果是播放狀态就會暫停,暫停狀态時就會繼續播放。

2、擷取播放檔案的總時間和目前播放進度

執行下面代碼時,Mplayer将時間在标準輸出顯示。

process->write("get_time_pos/n");

process->write("get_time_length/n");

通過如下代碼即可讀出我們需要的資訊:

connect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(back_message_slots()));

process有可讀取的資訊時,發出信号,在槽函數back_message_slots()中讀取資訊。

void MPlayer::back_message_slots()

{

while(process->canReadLine())

QString message(process->readLine());

//message即為讀取的資訊我們可以根據需要取我們要的資訊如

//檔案總時間為:ANS_LENGTH=23.00

//目前時間為:ANS_TIME_POSITION=23.00

}

3、快進功能

seek <value> [type]

Seek to some place in the movie.

0 is a relative seek of +/- <value> seconds (default).

1 is a seek to <value> % in the movie.

2 is a seek to an absolute position of <value> seconds.

下面代碼即可實作快進功能:

process->write(“seek ** 1/n”);

4、音量調節

volume <value> [abs]

Increase/decrease volume or set it to <value> if [abs] is nonzero.

Process->write(“volume -1/n”);           //音量減小

Process->write(“volume +1/n”);          //音量增加

5、靜音功能

mute [value]

Toggle sound output muting or set it to [value] when [value] >= 0

(1 == on, 0 == off).

process->write("mute 0/n");         //開啟靜音

process->write("mute 1/n");         //關閉靜音

6、定位視訊視窗

通過上面的代碼基本功能實作了,可是播放視訊的時候發現又彈出一個視窗。并沒有出現在我們的視窗裡。

如下代碼即可時間視窗的定位。

QString common = "mplayer -slave -quiet -ac mad -zoom movie/" + file_name + " -wid " + QString::number(widget->winId());

process->start(common);

紅色部分實作視窗的定位。Widget是一個QWidget對象。通過winId可以獲得一個數字,-wid既将視訊輸出定位到widget窗體部件中。

注意:-wid參數隻在X11、directX和OpenGL中适用。

四、PC環境下的實作過程

1、PC環境搭建

主機環境:Red Hat Enterprise Linux 5.0

交叉編譯工具:gcc-3.4.5-glibc-2.3.6

主機編譯工具:gcc-4.1.2

(1)主機端安裝mplayer

l         将“項目代碼/mplay源碼”目錄下的MPlayer-1.0rc2.tar.bz2、libmad-0.15.1b.tar.gz(1個mp3解碼庫)拷貝到linux系統中,如:/home/linux/mplayer目錄下

l         安裝libmad-0.15.1b.tar.gz

#tar xvfz libmad-0.15.1b.tar.gz

#cd libmad-0.15.1b

#./configure

#make

#mkdir /lib/lib

#mkdir /lib/include

#cp mad.h /lib/include

#cp .libs/libmad.a /lib/lib

l         安裝mplayer

#tar xvfj MPlayer-1.0.rc2.tar.bz2

#cd MPlayer-1.0rc2

#./configure --with-extraincdir=/lib/include --with-extralibdir=/lib/lib

#make install

此時可以試着播放一下mp3、avi等檔案了

# mplayer -ac mad 1.mp3

# mplayer -ac mad 2.avi

(2)安裝、移植qtopia-4.2.0

注:需要先按照5.2節将tslib按照好

l         将“項目代碼/qtopia源碼”目錄下的qtopia-opensource-src-4.2.0.tar.gz拷貝到linux系統中,如:/home/linux/Qtopia目錄下

# tar zxvf qtopia-opensource-src-4.2.0.tar.gz

# mv qtopia-opensource-4.2.0 source

# mkdir target  //建立在source同級目錄下建立目錄target

修改源碼包

# cd source

# cd src/libraries/qtopiabase/

# cp custom-linux-cassiopeia-g++.h custom-linux-arm-g++.h

# cp custom-linux-cassiopeia-g++.cpp custom-linux-arm-g++.cpp

修改時區資訊

# vi src/libraries/qtopia/qtimezone.cpp

将114行的 /usr/share/zoneinfo/ 改為/Qtipia/zoneinfo/ ,儲存退出。

# vi src/settings/systemtime/settime.cpp

将318行的 /usr/share/zoneinfo/ 改為/Qtipia/zoneinfo/ ,儲存退出。

l         裁減Qtopia core的庫(下列操作後在螢幕上會出現一個光标,否則沒有光标。根據需求配置)

# vi qtopiacore/qconfig-qpe.h

首先注釋掉關于滑鼠光标的宏定義,讓程式運作時,觸摸屏中央有光标出現:

// Qtopia Core

/*

#ifndef QT_NO_QWS_CURSOR

# define QT_NO_QWS_CURSOR

#endif

*/

#ifndef QT_NO_QWS_MOUSE

# define QT_NO_QWS_MOUSE

#ifndef QT_NO_QWS_MOUSE_AUTO

# define QT_NO_QWS_MOUSE_AUTO

其它宏定義根據需要進行注釋。

儲存後将qconfig-qpe.h拷貝到global目錄。

# cp qtopiacore/qconfig-qpe.h qtopiacore/qt/src/corelib/global/qconfig-qpe.h (必須進行的操作)

注釋掉其他檔案裡的QT_NO_QWS_CURSOR的定義

# vi qtopiacore/qt/src/corelib/global/qfeatures.h

注釋掉如下内容:

#if !defined(QT_NO_QWS_CURSOR) && (defined(QT_NO_CURSOR))

#define QT_NO_QWS_CURSOR

儲存退出。

# vi qtopiacore/qt/src/corelib/global/qglobal.h

注釋掉以下内容:

//# define QT_NO_QWS_CURSOR

#vim qtopiacore/qt/tools/qvfb/qvfbshmem.cpp

注釋掉asm/page.h

//#include <asm/page.h>

#vim qtopiacore/qt/tools/qvfb/qvfbmmap.cpp

并修改如下内容

unsigned char *data;

uint data_offset_value = sizeof(QVFbHeader);

if (data_offset_value % PAGE_SIZE)

data_offset_value += PAGE_SIZE - (data_offset_value % PAGE_SIZE);

為:

const int page_size = getpagesize();

if (data_offset_value % page_size)

data_offset_value += page_size - (data_offset_value % page_size);

# vim src/libraries/qtopiabase/qmemoryfile_unix.cpp +128

修改

f = :pen(tmpFile.toLatin1(), O_CREAT | O_WRONLY);

f = :pen(tmpFile.toLatin1(), O_CREAT | O_WRONLY ,0777);

l         修改交叉工具

#vim qtopiacore/qt/mkspecs/qws/linux-arm-g++/qmake.conf

将檔案中的arm-linux-***全部修改為arm-softfloat-linux-gnu-**

這樣做的前提是我的交叉工具鍊是arm-softfloat-linux-gnu,如果你的是arm-linux就不用改了。

l         生成Makefile

#cd ../target    //為了不破壞源碼,選擇在此目錄下配置、編譯源碼

#../source/configure -release -image /Qtopia -prefix /Qtopia -xplatform linux-arm-g++ -arch arm -no-qvfb -displaysize 320x240 -no-modem -extra-qtopiacore-config "-release -xplatform qws/linux-arm-g++ -embedded arm -qconfig qpe -depths 4,8,16,32 -qt-sql-sqlite -no-mouse-linuxtp -qt-mouse-tslib -I/home/linux/tslib/include -L/home/linux/tslib/lib " 2>../configureERR.txt

注意:這裡/Qtopia是最後Qtopia的安裝路徑,安裝到主機的某個路徑下,最終這個路徑和目标闆上的路徑必須一緻。

主要配置選項說明如下:

-xplatform linux-arm-g++ -arch arm

目标平台為arm-linux,體系結構為arm。

-no-qvfb

目标平台已支援framebuffer,因而不使用虛拟幀緩沖。

-extra-qtopiacore-config

為Qtopia core 配置選項。

-xplatform qws/linux-arm-g++ -embedded arm

目标平台編譯配置檔案使用qtopiacore/qt/mkspecs/qws/linux-arm-g++目錄下的配置檔案,嵌入式平台為arm。

-qconfig qpe

使用配置檔案qconfig-qpe.h,若使用qconfig-large.h配置檔案,則使用-qconfig large選項。

-qt-sql-sqlite

資料庫支援Sqlite。

-qt-kbd-usb

鍵盤支援usb協定。

-no-mouse-linuxtp -qt-mouse-tslib

-I/home/linux/tslib/include -L/home/linux/tslib/lib

觸摸屏協定不支援linuxtp,支援tslib,并在後面添加上剛才編譯的tslib的頭檔案和庫。

2>../qtopiaconfigureERR.txt

最後将配置過程中的錯誤輸出到qtopiaconfigureERR.txt檔案中。

l         編譯

l         将安裝和的目錄考到nfsroot目錄下

#cp /Qtopia /rootfs -a

(3)熟悉主機開發環境

l         提供給PC端的開發工具

上面的qtopia編譯安裝完成後,會在咱們前面建立的target目錄下生成很多開發工具。

先看一下供主機端使用的工具

[root@localhost bin]# pwd

/home/linux/Qtopia/target/qtopiacore/host/bin

[root@localhost bin]# ls

assistant  linguist  lupdate  qmake  rcc        uic

designer   lrelease  moc      qvfb   templates  uic3

如果系統以前有其它qt開發工具,把環境變量修改一下,保證它們不要和我們這幾個工具沖突。下面可以試一下你的designer了。

#./designer

2、在PC端實作基于qt前端的mplayer播放器

建立工程目錄/home/linux/mplayer

(1)搭建ui界面

利用前面安裝的designer搭建ui界面,并将其儲存至/home/linux/mplayer/mplayer.ui

圓角矩形标注: 加了一個widget,留作mplayer的播放區

(2)編寫程式

在/home/linux/mymplayer/下建立mplayer.cpp、mplayer.h、main.cpp 、image.qrc

Main.cpp

/*****************************main.cpp*****************************/

#include <QApplication>

#include "mplayer.h"

int main(int argc, char **argv)

QApplication app(argc, argv);

MPlayer player;   //執行個體最終的MPlayer類

player.show();     //顯示界面

return app.exec();  //運作程式

mplayer.h

#ifndef _MPLAYER_H

#define _MPLAYER_H

#include <QIcon>

#include <QProcess>

#include <QTimer>

#include <QStringList>

#include <QDir>

#include <QTime>

#include <QString>

#include "ui_mplayer.h"

class MPlayer:public QDialog,private Ui_Dialog

Q_OBJECT

public:

MPlayer(QWidget *parent = 0);

QTime int_to_time(int);

public slots:            

void play_pause_slots(); //暫停

void stop_slots();      //停止

void previous_slots();   //上一曲

void next_slots();       //下一曲

void seek_slots(int);

void get_time_slots();        //得到播放時間

void set_volume_slots(int);    //設定音量

void set_sound_slots();       //靜音

void playerReward_slots();    //快退

void playerForward_slots();    //快進

void back_message_slots();    //更新顯示資訊

private:

QProcess *process;

QStringList files;

QDir directory;

int file_count;

QString file_name;

bool isPlay;

bool isSound;

bool isStop;

QTimer *timer;

int file_length;

int curr_time;

};

mplayer.cpp

/*******************************mplayer.cpp **********************************/

#include <QDebug>

#include <unistd.h>

MPlayer::MPlayer(QWidget *parent)Dialog(parent)

setupUi(this);  //初始化界面

isPlay = true;

isSound = true;

isStop = false;

/************************為按鍵添加圖示**************************/

//play

QIcon icon_play;

icon_play.addPixmap(QPixmap(QString::fromUtf8("images/pause_enabled.png")), QIcon::Normal, QIcon::Off);

pushButton_2->setIcon(icon_play);

//stop

QIcon icon_stop;

icon_stop.addPixmap(QPixmap(QString::fromUtf8("images/stop_enabled.png")), QIcon::Normal, QIcon::Off);

pushButton_3->setIcon(icon_stop);

//reward

QIcon icon_reward;

icon_reward.addPixmap(QPixmap(QString::fromUtf8("images/reward_enabled.png")), QIcon::Normal, QIcon::Off);

pushButton_4->setIcon(icon_reward);

//forward

QIcon icon_forward;

icon_forward.addPixmap(QPixmap(QString::fromUtf8("images/forward_enabled.png")), QIcon::Normal, QIcon::Off);

pushButton_5->setIcon(icon_forward);

//sound

QIcon icon_sound;

icon_sound.addPixmap(QPixmap(QString::fromUtf8("images/sound_enabled.png")), QIcon::Normal, QIcon::Off);

pushButton->setIcon(icon_sound);

QIcon icon_previous;

icon_previous.addPixmap(QPixmap(QString::fromUtf8("images/previous_disabled.png")), QIcon::Normal, QIcon::Off);

pushButton_6->setIcon(icon_previous);

QIcon icon_next;

icon_next.addPixmap(QPixmap(QString::fromUtf8("images/next_enabled.png")), QIcon::Normal, QIcon::Off);

pushButton_7->setIcon(icon_next);

/************************設定按鈕無邊框**********************************/

pushButton->setFlat(true);

pushButton_2->setFlat(true);

pushButton_3->setFlat(true);

pushButton_4->setFlat(true);

pushButton_5->setFlat(true);

pushButton_6->setFlat(true);

pushButton_7->setFlat(true);

/*************************獲得播放清單***************************/

directory.setPath("./movie");

files = directory.entryList(QDir::AllEntries,QDir::Time);

file_name = files[2]; //檔案0和1為 ”.” ”..”,是以從檔案2開始播放

file_count = 2;

label_3->setText(files[2]);

/*************************初始化進度條及QProcess類**************/

horizontalSlider->setPageStep(1);

process = new QProcess(this);

/*************************初始化信号、槽*************************/

connect(pushButton_2,SIGNAL(clicked()),this,SLOT(play_pause_slots()));

connect(pushButton_3,SIGNAL(clicked()),this,SLOT(stop_slots()));

connect(pushButton_4,SIGNAL(clicked()),this,SLOT(playerReward_slots()));

connect(pushButton_5,SIGNAL(clicked()),this,SLOT(playerForward_slots()));

connect(pushButton_6,SIGNAL(clicked()),this,SLOT(previous_slots()));

connect(pushButton_7,SIGNAL(clicked()),this,SLOT(next_slots()));

//connect(horizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(seek_slots(int)));

connect(spinBox,SIGNAL(valueChanged(int)),this,SLOT(set_volume_slots(int))); 

connect(pushButton,SIGNAL(clicked()),this,SLOT(set_sound_slots()));

//當process可以讀到Mplayer的傳回資訊時,産生readyReadStandardOutput()信号

//process->start("mplayer -slave -quiet -ac mad 2.avi");

//add -wid QWidget->winId();

QString common = "mplayer -slave -quiet -ac mad -zoom movie/" + file_name + " -wid " + QString::number(widget->winId()); //這裡的widget是ui中MPlayer的顯示區

process->start(common);      //開始運作程式

spinBox->setValue(40);     

timer = new QTimer(this);

connect(timer,SIGNAL(timeout()),this,SLOT(get_time_slots()));

//定時擷取MPlayer的時間資訊

timer->start(1000); //啟動定時器 1秒timeout 1次

void MPlayer::play_pause_slots()

if(!isPlay)

if(isStop)

file_name = files[file_count];

else

process->write("pause/n");

QIcon icon_pause;

icon_pause.addPixmap(QPixmap(QString::fromUtf8("images/play_enabled.png")), QIcon::Normal, QIcon::Off);

pushButton_2->setIcon(icon_pause);

isPlay = false;

void MPlayer::stop_slots()

if(!isStop)

process->write("quit/n");

icon_stop.addPixmap(QPixmap(QString::fromUtf8("images/stop_disabled.png")), QIcon::Normal, QIcon::Off);

isStop = true;

label->setText("00:00:00");

label_2->setText("00:00:00");

void MPlayer::previous_slots()

if(file_count > 2)

if(file_count == (files.size()-1))

file_count--;

if(file_count == 2)

label_3->setText(files[file_count]);

void MPlayer::next_slots()

if(file_count < (files.size()-1))

icon_previous.addPixmap(QPixmap(QString::fromUtf8("images/previous_enabled.png")), QIcon::Normal, QIcon::Off);

process->write("quit/n");     

file_count++;

{   

icon_next.addPixmap(QPixmap(QString::fromUtf8("images/next_disabled.png")), QIcon::Normal, QIcon::Off);

void MPlayer::seek_slots(int seek_num)

qDebug()<<seek_num;

if(process && process->state() == QProcess::Running )

process->write(QString("seek " + QString::number(qMin(seek_num,100)) + "1/n").toAscii());

void MPlayer::get_time_slots()

if(isPlay)

void MPlayer::set_volume_slots(int volume)

qDebug()<<volume;

process->write(QString("volume +" + QString::number(volume) + " /n").toAscii());

//process->write(QString("volume +1/n").toAscii());

void MPlayer::set_sound_slots()

if(isSound)

process->write("mute 1/n");

icon_sound.addPixmap(QPixmap(QString::fromUtf8("images/nosound_enabled.png")), QIcon::Normal, QIcon::Off);

isSound = false;

process->write("mute 0/n");

void MPlayer::playerReward_slots()

//bool ok;

//int m=moviePosition.toInt(&ok);

if (process && process->state()==QProcess::Running && !isPlay)

//QString cmd="seek "+QString::number(qMax(m-10,0))+" 1/n";

//process->write(cmd.toAscii());

qDebug()<<"Reward";

void MPlayer::playerForward_slots()

//     groupBox->setVisible(false);

/*    if (process && process->state()==QProcess::Running && !isPlay)

//QString cmd="seek "+QString::number(qMin(m+10,100))+" 1/n";

qDebug()<<"Forward";

}*/

QStringList message_list = message.split("=");

if(message_list[0] == "ANS_TIME_POSITION")

curr_time = message_list[1].toDouble();//toInt();

QTime time = int_to_time(curr_time);

label->setText(time.toString("hh:mm:ss"));

horizontalSlider->setValue(100 * curr_time / file_length);

else if(message_list[0] == "ANS_LENGTH")

file_length = message_list[1].toDouble();//toInt();

QTime time = int_to_time(file_length);

label_2->setText(time.toString("hh:mm:ss"));     

QTime MPlayer::int_to_time(int second)

int sec = 0, min = 0, hour = 0;

QTime time;

if(second < 60)    

sec = second;

min = 0;

hour = 0;

if(second >= 60 && second < 3600)

sec = second % 60;

min = second / 60;

if(second >= 3600)

min = (second / 60) % 60;

hour = second / 3600;

time.setHMS(hour,min,sec);

return time;

image.qrc

<RCC>

<qresource prefix="images" >

<file>images/player_play.png</file>

<file>images/player_stop.png</file>

<file>images/player_pause.png</file>

<file>images/play_enabled.png</file>

<file>images/pause_enabled.png</file>

<file>images/reward_enabled.png</file>

<file>images/forward_enabled.png</file>

<file>images/stop_enabled.png</file>

<file>images/sound_enabled.png</file>

<file>images/nosound_enabled.png</file>

<file>images/previous_enabled.png</file>

<file>images/previous_disabled.png</file>

<file>images/next_enabled.png</file>

<file>images/next_disabled.png</file>

</qresource>

</RCC>

(3)編譯工程

l         拷貝qmake到目前工程目錄下

#cp /home/linux/Qtopia/target/qtopiacore/host/bin/qmake ./

l         生成項目檔案、

#qmake –project

#qmake

成功後,可以生成mplayer可執行程式

l         建立movie和images

#mkdir movie

#mkdir images

[root@localhost mplayer]# ls movie/

1.mp3  2.avi  3.avi  4.avi  5.avi

[root@localhost mplayer]# ls images

forward_enabled.png  nosound_enabled.png  player_play.png        reward_enabled.png

images               pause_enabled.png    player_stop.png        sound_enabled.png

next_disabled.png    play_enabled.png     previous_disabled.png  stop_disabled.png

next_enabled.png     player_pause.png     previous_enabled.png   stop_enabled.png

l         運作程式

[root@localhost mplayer]#./mplayer

五、移植到ARM平台過程

1、核心要求

要求核心支援framebuffer驅動、OSS音頻驅動、支援input事件的觸摸屏驅動。

2、目标闆上部署qt環境

将前面交叉編譯好的/Qtopia目錄拷貝到nfsroot目錄下

#cp /Qtopia /rootfs –a

注:rootfs為目标平台的nfs根檔案系統位置

3、檔案系統中移植tslib

(下面的步驟是在ubantu-8.10環境下編譯的,其它的系統基本相同)

(1)拷貝“項目代碼/tslib源碼”目錄下的tslib-1.4.tar.gz到linux系統

(2)# tar -zxvf tslib-1.4.tar.gz

# cd tslib-1.4

# ./autogen.sh

這一步需要安裝一些工具,如:在ubantu系統下可以執行:sudo apt-get install automake

(3)執行autogen.sh腳本所生成的Makefile檔案

請打入以下指令:

echo "ac_cv_func_malloc_0_nonnull=yes" >$ARCH-linux.cache

./configure --host=arm-softfloat-linux-gnu  --prefix=/home/linux/tslib --cache-file=$ARCH-linux.cache

--host是指你的交叉編譯器的前最;例如:你的交叉編譯器是arm-linux-gcc,則--host=arm-linux.如果是arm-softfloat-linux-gnu-gcc

則--host=arm-softfloat-linux-gnu

--prefix 是你執行make install 的時候編譯後生成的可執行檔案和庫檔案以及配置文所安裝的目錄;

configure檔案下還有好多選項,你可以執行./configure --help 來進行選擇其他項,不過在這裡這些選項就夠了。

(4)#make

(5)把指定安裝目錄下的mytslib的檔案都copy到你所挂載的根檔案下

#cp -rf /home/linux/tslib/*    /rootfs/tslib

(6)修改/rootfs/tslib下的etc目錄中ts.cong檔案

#vi ts.conf  将第二行的#module_raw input修改成module_raw input 注意一定要頂格寫否則程式執行時會發生讀取ts.conf錯誤

(7)啟動你的開發闆

在終端上設定一下環境變量:

export TSLIB_ROOT=/mytslib

export TSLIB_TSDEVICE=/dev/event0

export LD_LIBRARY_PATH=/mytslib/libLD_LIBRARY_PATH

export QWS_SIZE=320x240

export TSLIB_FBDEVICE=/dev/fb0

export TSLIB_PLUGINDIR=/mytslib/lib/ts

export TSLIB_CONSOLEDEVICE=none

export TSLIB_CONFFILE=/mytslib/etc/ts.conf

export POINTERCAL_FILE=/etc/pointercal

export QWS_MOUSE_PROTO=Tslib:/dev/event0

export TSLIB_CALIBFILE=/etc/pointercal

export QWS_DISPLAY="LinuxFb:mmWidth100:mmHeight130:0"

export TSLIB_TSEVENTTYYPE=H3600

為了實作Tslib的正确運作,需要對如下的Tslib的環境變量進行配置:

TSLIB_TSDEVICE  //觸摸屏裝置檔案名。

TSLIB_CALIBFILE  //校準的資料檔案,由ts_calibrate校準程式生成。

SLIB_CONFFILE  //配置檔案名。

TSLIB_PLUGINDIR //插件目錄

TSLIB_CONSOLEDEVICE //控制台裝置檔案名

TSLIB_FBDEVICE  //裝置名

以上環境變量在實際開發中的實際配置可以根據實際情況決定。而這些指定的裝置節點一定要和你的開發闆上的/dev目錄下的裝置節點相對應。

為了不浪費時間我們把上面的這些設定寫入一個腳本裡面:參見5.6節

(8)就可以運作mytslib/bin下的測試檔案,如ts_calibrate校準程式。

4、檔案系統中移植mplayer播放器

需要在目标闆上也移植開源的mplayer播放器,步驟如下:

l         編譯libmad

重新配置前面針對主機編譯過的libmad

#./configure --enable-fpm=arm --host=arm-linux --disable-shared /

--disable-debugging --prefix=/usr/local/arm/3.4.1/lib /

CC=arm-linux-gcc

就可以編譯出libmad了。注意--prefix配置選項表示libmad庫和頭檔案在哪個目錄生成,比如本例中make install後在/usr/local/arm/3.4.1/lib目錄下就多了include和lib兩個目錄。這與mplayer的配置選項--with-extraincdir指定的目錄是相符的。如果沒找到編譯生成的lib庫和include頭檔案。則在目前編譯目錄下的mad.h以及.libs目錄下的libmad.a拷到你自己指定的目錄下

l         編譯mplayer

./configure --cc=arm-linux-gcc --host-cc=gcc --target=arm-linux --enable-static /

--prefix=/tmp/mplayer-rc2 --disable-win32dll --disable-dvdread /

--enable-fbdev --disable-mencoder --disable-live --disable-mp3lib /

--enable-mad --enable-libavcodec_a --language=zh_CN /

--disable-armv5te --disable-armv6 /

--with-extraincdir=/usr/local/arm/3.4.1/lib/include /

--with-extralibdir=/usr/local/arm/3.4.1/lib/lib

幾點注意:—host-cc參數指定X86的gcc,不指定的話,有些必須用gcc編譯的,make會交叉編譯,就會出錯

--cc指定交叉工具鍊名稱

--with-extraincdir與--with-extralibdir指定剛才交叉編譯libmad生成的mad.h與liblibmad.a存放路徑

編譯過程中會出現如下錯誤:

armv4l/dsputil_arm_s.S:79:error:selected processor does not support 'pld[r1]'

【解決辦法】

修改dsputil_arm_s.S,在前面添加上:

#ifndef HAVE_PLD

.macro pld reg

.endm

5、主機交叉編譯工程

(1)針對目标平台調整UI

由于目标平台的液晶是320*240分辨率的,是以需要調整下UI的大小。将UI的整個視窗大小調整為320*240。

(2)交叉編譯工程

l         拷貝針對目标平台的qmake工具到工程目錄下

#cp /home/linux/Qtopia/target/qtopiacore/target/bin/qmake ./

l         生成項目檔案

l         生成Makefile檔案

l         編譯生成目标檔案mymplayer

6、設定環境變量腳本檔案Qtopia.sh

#vim Qtopia.sh

!/bin/sh

export TSLIB_ROOT=/tslib

export LD_LIBRARY_PATH=/tslib/libLD_LIBRARY_PATH

export TSLIB_PLUGINDIR=/tslib/lib/ts

export TSLIB_CONFFILE=/tslib/etc/ts.conf

export TSLIB_TSEVENTTYYPE=H3600i

export LD_LIBRARY_PATH=/Qtopia/libLD_LIBRARY_PATH

export QWS_SW_CURSOR

export set HOME=/root

export set QPEDIR=/Qtopia

export set QWS_KEYBOARD="TTY:/dev/tty1"

export QWS_DISPLAY="LinuxFb:mmWidth60:mmHeight65:0"   

7、通過nfs方式測試程式

(1)設定uboot參數

setenv bootcmd tftp 30008000 zImage /; go zImage

setenv bootargs root=nfs nfsroot=192.168.1.112:/rootfs ip=192.168.1.202 init=/linuxrc console=ttySAC0,115200 devfs=mount display=sam240

(2)啟動目标系統

l         将“項目代碼/工程鏡像”目錄下的zImage拷貝到tftp服務目錄/tftpboot下

l         開啟nfs、tftp服務,服務目錄分别為/rootfs /tftpboot

l         啟動系統

l         運作測試程式

#. ./Qtopia.sh  //設定環境變量

#./mymplayer –qws  //運作程式

8、QT程式國際化

利用/home/linux/Qtopia/target/qtopiacore/host/bin下面的幾個工具給程式做漢化工作

(1)修改pro檔案

在.pro檔案添加如下内容:

TRANSLATIONS = zh_CN.ts

(2)生成ts檔案

#lupdate mymplayer.pro

生成zh_CN.ts檔案

(3)生成qm翻譯檔案

#linguist zh_CN.ts

(4)拷貝字型檔案到目标系統

l         從C:/WINDOWS/Fonts選擇一個字型,如simsun.ttc

cp simsun.ttc /rootfs/Qtopia/lib/fonts           //simsun.ttc 是宋體字庫

l         修改fonts中檔案fontdir,添加如下内容

simsun simsun.ttc TTC n 50 120 u    

(5)修改源碼

修改main.cpp為如下形式

#include <QtCore/QTextCodec>

#include <QTranslator>

QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")) ;//設定編碼為UTF8

app.setFont(QFont("simsun", 10));                            //設定顯示字型為漢字

QTranslator *translator = new QTranslator( 0 );                              //導入中文化qm檔案

translator->load( "zh_CN.qm", "." );

app.installTranslator( translator );

MPlayer player;

player.show();

return app.exec();

9、目标機獨立測試

(1)裁剪系統

(2)制作cramfs鏡像

繼續閱讀