天天看點

J2me流媒體技術實作讨論[1]

看到很多很多人持續在問這個問題。

以前我也聽說,好像kvm底層實作不太支援j2me來做streaming video/audio,但我不知道那人為什麼這麼說。

那麼現在國外有一個人提出下面這種思路,并且号稱在<b>nokia6260</b>[相關資料:諾基亞 6260 nokia62602.0 (3.0436.0) symbianos7.0s series602.1 profilemidp-2.0 configurationcldc-1.0]

上真實實作了(<b>兩種網絡方式:藍牙和</b><b>gprs</b><b>都試驗過</b>),但我懷疑他的前提條件是“<b>你的手機必須允許同時實作</b><b>player</b><b>的多個執行個體進入</b><b>prefetched</b><b>狀态(預讀取聲音流)</b>”:

第一步:

聲明兩個player;

第二步:

httpconnection開始向伺服器請求該audio檔案的第一部分位元組,我們定這次讀取的位元組數為18kb;

第三步:

等第一部分資料到位後,player a開始realize和prefetch,并開始播放;

第四步:

在player a播放同時,(18kb的amr資料可以播放10秒鐘),httpconnection繼續請求第二部分資料(假設gprs每秒鐘傳輸3kb,那麼18kb需要傳輸6秒,算上前後通訊損失的時間,應該不會超過10秒鐘);

第五步:

第二部分資料到位後,假設player a還沒有播放完(這需要調整你的每一部份資料位元組數來使得假設成立),那麼将資料喂給player b讓它realize和prefetch;

第六步:

player a播放完後,得到事件通知,于是讓player b開始播放。

如此往複。

大家看看此種理論可否。

我自己在nokia 7610上測試了一下,我上面說的前提被證明是可行的:“<b>你的手機必須允許同時實作player的多個執行個體進入prefetched狀态(預讀取聲音流)</b>”。真實nokia手機确實可以如此:

兩個線程中各自有一個player,都開始做m_player.realize();和m_player.prefetch();,然後等候。

先播放線程1的player,等她播放完後,

通過

J2me流媒體技術實作讨論[1]

/*

J2me流媒體技術實作讨論[1]

  * 本類實作了playerlistener接口。通過這個事件來告知媒體已經播放完畢

J2me流媒體技術實作讨論[1]

  */

J2me流媒體技術實作讨論[1]

public void playerupdate(player player, string event, object data){

J2me流媒體技術實作讨論[1]

  if(event == playerlistener.end_of_media){

J2me流媒體技術實作讨論[1]

   try{

J2me流媒體技術實作讨論[1]

    system.out.println("playerupdate&gt;&gt;playerlistener.end_of_media");

J2me流媒體技術實作讨論[1]

    stopgauge();

J2me流媒體技術實作讨論[1]

    playforeground();

J2me流媒體技術實作讨論[1]

   }catch(exception e){

J2me流媒體技術實作讨論[1]

    e.printstacktrace();

J2me流媒體技術實作讨論[1]

   }

J2me流媒體技術實作讨論[1]

  }

J2me流媒體技術實作讨論[1]

}

J2me流媒體技術實作讨論[1]

來通知第二個線程的player播放。

這樣是可以的。

qinjiwy說“可以,不過前提是該音頻檔案允許分段播放,有些音頻檔案就是不允許的.”,你說得對。确實有很多格式的媒體檔案不支援分段播放。我所知道的是wav可以,mp3也可以。

服務端每次隻讀取這兩種媒體檔案的某一部分,如果是mp3檔案的話,我暫時不知道是否每次需要加上特殊的頭資訊。 

但是如果是wav檔案,那麼肯定每次都要加上wav特定的頭,要不然player也無法播放。 

這種形式肯定是可行的。因為以前我在vc++上寫text to speech程式時,就是這麼做的:wav檔案的前若幹個位元組肯定是頭資訊,這是一定的,随後跟的全是raw data;我每一次讀取wav的raw data若幹位元組後,傳給我的播放線程,他需要給這段raw data前加上一個wav header,然後就可以正常播放了。 

server side java code:

J2me流媒體技術實作讨論[1]

public void transfer(dataoutputstream output) {

J2me流媒體技術實作讨論[1]

         try{  

J2me流媒體技術實作讨論[1]

                   int i = 0;

J2me流媒體技術實作讨論[1]

                   int auglis = 50058; //chunk size

J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]

                //if it is wav file, we need to edit header:

J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]

                   //audio[4] = (byte)0x8a;

J2me流媒體技術實作讨論[1]

                   //     audio[5] = (byte)0xc3;

J2me流媒體技術實作讨論[1]

                  //  audio[6] = (byte)0x00;

J2me流媒體技術實作讨論[1]

                  //  audio[7] = (byte)0x00;

J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]

                   //  audio[54] = (byte)0x50;

J2me流媒體技術實作讨論[1]

                  //  audio[55] = (byte)0xc3;

J2me流媒體技術實作讨論[1]

                  // audio[56] = (byte)0x00;

J2me流媒體技術實作讨論[1]

                  // audio[57] = (byte)0x00;

J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]

                   byte[] tmp = new byte[50058];

J2me流媒體技術實作讨論[1]

                   int countbytes= 0;

J2me流媒體技術實作讨論[1]

                   int headerup = 32; //mp3 header is 32 bytes.

J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]

                while(i&lt;50058){

J2me流媒體技術實作讨論[1]

                 tmp[i] = audio[i]; //byte array audio is byte array from mp3 file

J2me流媒體技術實作讨論[1]

                 i++;

J2me流媒體技術實作讨論[1]

                 countbytes++;

J2me流媒體技術實作讨論[1]

                   }  

J2me流媒體技術實作讨論[1]

                output.writeint(50058);     //write to midlet, that chunk size will be 50058

J2me流媒體技術實作讨論[1]

                output.write(tmp);   //write chunk itself

J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]

                   boolean varam = true; //booleand that will become false, when file ends

J2me流媒體技術實作讨論[1]

                   while(varam){

J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]

                   int tmplen = garums - countbytes; //check if it is not last chunk

J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]

                   int o=50058;

J2me流媒體技術實作讨論[1]

                   if(tmplen&gt;50058){ //if it is not last chunk

J2me流媒體技術實作讨論[1]

                     o = 50058;  

J2me流媒體技術實作讨論[1]

                   }

J2me流媒體技術實作讨論[1]

                   else{

J2me流媒體技術實作讨論[1]

                   o = tmplen+headerup; // if it is last chunk

J2me流媒體技術實作讨論[1]

                   tmp = new byte[o];

J2me流媒體技術實作讨論[1]

                   varam = false; //out while loop will end

J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]

                       int z = 0;

J2me流媒體技術實作讨論[1]

                       while(z&lt;32){ //write 32 byte header to chunk

J2me流媒體技術實作讨論[1]

                       tmp[z] = audio[z];          

J2me流媒體技術實作讨論[1]

                       z++;

J2me流媒體技術實作讨論[1]

                       countbytes++;

J2me流媒體技術實作讨論[1]

                       }   

J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]

                       while(z&lt;o){ //white chunk it self

J2me流媒體技術實作讨論[1]

                       tmp[z] = audio[i];

J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]

                       i++;

J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]

                       }  

J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]

                  headerup =  headerup +32;

J2me流媒體技術實作讨論[1]

                  output.writeint(o);          //white size of chunk (typically 50058)

J2me流媒體技術實作讨論[1]

                  output.write(tmp);    //white chunk itself

J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]
J2me流媒體技術實作讨論[1]

         }

J2me流媒體技術實作讨論[1]

         catch (exception e) {}

J2me流媒體技術實作讨論[1]

    }

J2me流媒體技術實作讨論[1]