zoukankan      html  css  js  c++  java
  • J2me流媒体技术实现讨论[1]

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

    以前我也听说,好像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,然后就可以正常播放了。

    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) {}
        }

     

  • 相关阅读:
    今天被编码搞惨了,页面和脚本的编码一致性
    在IE下FLASH背景透明而在FF下不透明的解决方法
    仿FLASH 的大图切换效果 图片切换 jQuery 圣诞节
    仿ABCNEWS 的新闻切换效果
    preventDefault() 方法 取消掉与事件关联的默认动作
    jQuery 投票调查组件
    js常用脚本 判断浏览器
    Django 之 drf 第三篇 视图类 路由的使用
    Django框架之drf 之一 [restful规范 APIview源码分析 Request类分析 序列化组件 ]
    django框架之十一 Auth模块
  • 原文地址:https://www.cnblogs.com/zhengyun_ustc/p/j2mestreamingaudio.html
Copyright © 2011-2022 走看看