看到很多很多人持續在問這個問題。
以前我也聽說,好像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,等她播放完後,
通過
/*
* 本類實作了playerlistener接口。通過這個事件來告知媒體已經播放完畢
*/
public void playerupdate(player player, string event, object data){
if(event == playerlistener.end_of_media){
try{
system.out.println("playerupdate>>playerlistener.end_of_media");
stopgauge();
playforeground();
}catch(exception e){
e.printstacktrace();
}
}
}
來通知第二個線程的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:
public void transfer(dataoutputstream output) {
try{
int i = 0;
int auglis = 50058; //chunk size
//if it is wav file, we need to edit header:
//audio[4] = (byte)0x8a;
// audio[5] = (byte)0xc3;
// audio[6] = (byte)0x00;
// audio[7] = (byte)0x00;
// audio[54] = (byte)0x50;
// audio[55] = (byte)0xc3;
// audio[56] = (byte)0x00;
// audio[57] = (byte)0x00;
byte[] tmp = new byte[50058];
int countbytes= 0;
int headerup = 32; //mp3 header is 32 bytes.
while(i<50058){
tmp[i] = audio[i]; //byte array audio is byte array from mp3 file
i++;
countbytes++;
}
output.writeint(50058); //write to midlet, that chunk size will be 50058
output.write(tmp); //write chunk itself
boolean varam = true; //booleand that will become false, when file ends
while(varam){
int tmplen = garums - countbytes; //check if it is not last chunk
int o=50058;
if(tmplen>50058){ //if it is not last chunk
o = 50058;
}
else{
o = tmplen+headerup; // if it is last chunk
tmp = new byte[o];
varam = false; //out while loop will end
int z = 0;
while(z<32){ //write 32 byte header to chunk
tmp[z] = audio[z];
z++;
countbytes++;
}
while(z<o){ //white chunk it self
tmp[z] = audio[i];
i++;
}
headerup = headerup +32;
output.writeint(o); //white size of chunk (typically 50058)
output.write(tmp); //white chunk itself
}
catch (exception e) {}
}