J2me流媒体技术实现讨论[1]

news/2024/7/15 20:56:09

看到很多很多人持续在问这个问题。

以前我也听说,好像kvm底层实现不太支持j2me来做streaming video/audio,但我不知道那人为什么这么说。

那么现在国外有一个人提出下面这种思路,并且号称在Nokia6260[相关数据:诺基亚 6260 Nokia62602.0 (3.0436.0) SymbianOS7.0s Series602.1 ProfileMIDP-2.0 ConfigurationCLDC-1.0]

上真实实现了(两种网络方式:蓝牙和GPRS都试验过),但我怀疑他的前提条件是你的手机必须允许同时实现player的多个实例进入prefetched状态(预读取声音流)

第一步:
声明两个Player

第二步:
HttpConnection
开始向服务器请求该audio文件的第一部分字节,我们定这次读取的字节数为18KB

第三步:
等第一部分数据到位后,Player A开始realizeprefetch,并开始播放;

第四步:
Player A播放同时,(18KBamr数据可以播放10秒钟)HttpConnection继续请求第二部分数据(假设GPRS每秒钟传输3KB,那么18KB需要传输6秒,算上前后通讯损失的时间,应该不会超过10秒钟)

第五步:
第二部分数据到位后,假设Player A还没有播放完(这需要调整你的每一部份数据字节数来使得假设成立),那么将数据喂给Player B让它realizeprefetch

第六步:
Player A
播放完后,得到事件通知,于是让Player B开始播放。

如此往复。

大家看看此种理论可否。

     我自己在nokia 7610上测试了一下,我上面说的前提被证明是可行的:你的手机必须允许同时实现player的多个实例进入prefetched状态(预读取声音流)。真实Nokia手机确实可以如此:
两个线程中各自有一个Player,都开始做m_player.realize();m_player.prefetch();,然后等候。

先播放线程1Player,等她播放完后,
通过

 

 

/*
  * 本类实现了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;我每一次读取WAVRAW DATA若干字节后,传给我的播放线程,他需要给这段RAW DATA前加上一个WAV HEADER,然后就可以正常播放了。

20060115增补:

Huang的Mobcast,确实非常著名,几个月以前,在我写toodouPodcastMidlet时就看过许多人介绍过他,但是就是连不上http://www.geocities.com/tvhuangsg/mobcast/这个地址,所以一直未睹真容。

转换各种格式的video为3gp,转换各种格式的audio为amr,这些在开源软件mplayer手下是随手拈来,只需要看懂mplayer的各种参数即可做到了。所以拜mplayer所赐,我也能够制作手机看交通实况录像,都要感谢那些mplayer的开发人员!

"移动收听必须对中断事件进行管理",这个确实需要考虑。当进入Paused状态时,需要通知播放线程暂停,同时连接线程暂时就不要去抓取服务器的媒体数据了;等界面切换回来后,播放线程继续replay,连接线程继续下载音乐。

cleverpig说“可以通过人工(或者用程序)将文件分割后部署放到服务器上来解决”,我想也是,简单的文件分割是不够的,或者说仅仅适合于wav这种原始数据格式。应该事先将音乐文件用mencoder分解成一段一段的音乐文件放在服务器上,mencoder将处理每一段的格式问题保证能独立播放,这样手机下载起来只需要按照编号一段一段地下载即可,服务器不再需要运算和添加头信息。

美中不足,如果两个player切换播放,中间会有一个卡啪声。 

 

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];
                       z
++
;
                       i
++
;
                       countBytes
++
;
                       }
  
                          
                  headerup 
=  headerup +32
;
                  output.writeInt(o);          
//white size of chunk (typically 50058)

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

         
         
         }

         
catch (Exception e) {}
    }

 

 

 





http://www.niftyadmin.cn/n/3649718.html

相关文章

golang中使用指针_了解Go中的指针

golang中使用指针介绍 (Introduction) When you write software in Go you’ll be writing functions and methods. You pass data to these functions as arguments. Sometimes, the function needs a local copy of the data, and you want the original to remain unchanged…

RSS和社会性书签Chicklet创建器

“RSS and Social Bookmarking Chicklet Creator”&#xff0c;从名称上好像看不出来是做什么的&#xff0c;进去之后&#xff0c;你就明白了&#xff0c;那摸多的web 2.0参与者们&#xff0c;你们不正需要这套工具吗&#xff1f;它可以一次性帮你解决订阅按钮问题&#xff1a;…

命令行curl上传文件_命令行基础知识:使用cURL下载文件

命令行curl上传文件Client URL, or simple cURL is a library and command-line utility for transferring data between systems. It supports a myriad of different protocols and tends to be installed by default on many Unix-like operating systems. Because of it’s…

认识JSON Web令牌(JWT)

什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准&#xff08;(RFC 7519).该token被设计为紧凑且安全的&#xff0c;特别适用于分布式站点的单点登录&#xff08;SSO&#xff09;场景。JWT的声明一般被用来在身份提供者和服务提…

盘点我这三年

2003年&#xff1a;2003年伊始&#xff0c;就双喜临门&#xff0c;1月1日被正式任命为部门技术总监&#xff0c;同天搬入新家。这一时期必须要感谢田总邓总的悉心栽培和信任。2003年12月底&#xff0c;自己的blogcn网志“跟随大象的舞步”被当时刚刚成立一周年的中国博客网评选…

canvas动画:黑客帝国_使用Canvas API进行动画处理-第2部分:基本碰撞

canvas动画:黑客帝国In Part 1 of this series we went over the basics of rendering reusable objects to the canvas, using our GUI for more intuitive controls, and creating the illusion of basic movement with our animation loop. In this part we’ll get comfort…

体验Windows Live Mail Beta?

Webleon的《立即体验Windows Live Mail Beta》和Joey的《Live Mail beta初体验》&#xff0c;都写了如何升级hotmail到Windows Live Mail Beta来体验微软的最新战略。我倒是这么做了&#xff0c;先是只得到了25MB->250MB的容量升级&#xff0c;没见到界面改变为神奇的“信息…

Spring安全框架——jwt的集成(服务器端)

新建用户表——users&#xff0c;并完成数据库增删查改 一、新建表 二、持久化映射&#xff0c;建立模型类&#xff0c;添加主键生成器 //指定生成器名称GeneratedValue(generator "uuid2" )GenericGenerator(name "uuid2", strategy "org.hiber…