Subversion Repositories Kolibri OS

Rev

Rev 2427 | Blame | Last modification | View Log | Download | RSS feed

  1.  
  2. #include <stdint.h>
  3. #include <libavcodec/avcodec.h>
  4. #include <libavformat/avformat.h>
  5. #include <libswscale/swscale.h>
  6.  
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include "../winlib/winlib.h"
  10. #include "sound.h"
  11. #include "fplay.h"
  12.  
  13.  
  14. astream_t astream;
  15.  
  16. extern uint8_t *decoder_buffer;
  17.  
  18. extern volatile enum player_state player_state;
  19.  
  20. extern volatile uint32_t driver_lock;
  21.  
  22. static SNDBUF hBuff;
  23.  
  24. static int snd_format;
  25. int sample_rate;
  26.  
  27. static uint32_t samples_written = 0;
  28. double audio_base = -1.0;
  29.  
  30. double get_audio_base();
  31.  
  32. int init_audio(int format)
  33. {
  34.     int    err;
  35.     int    version =-1;
  36.     char  *errstr;
  37.  
  38.     mutex_lock(&driver_lock);
  39.  
  40.     if((err = InitSound(&version)) !=0 )
  41.     {
  42.         mutex_unlock(&driver_lock);
  43.         errstr = "Sound service not installed\n\r";
  44.         goto exit_whith_error;
  45.     };
  46.  
  47.     mutex_unlock(&driver_lock);
  48.  
  49.     printf("sound version 0x%x\n", version);
  50.  
  51.     if( (SOUND_VERSION>(version&0xFFFF)) ||
  52.         (SOUND_VERSION<(version >> 16)))
  53.     {
  54.         errstr = "Sound service version mismatch\n\r";
  55.         goto exit_whith_error;
  56.     }
  57.  
  58.     snd_format = format;
  59.  
  60.     create_thread(audio_thread, 0, 163840);
  61.  
  62.     return 1;
  63.  
  64. exit_whith_error:
  65.  
  66.     printf(errstr);
  67.     return 0;
  68. };
  69.  
  70. static uint64_t samples_lost;
  71. static double  audio_delta;
  72. static double  last_time_stamp;
  73.  
  74.  
  75. double get_master_clock(void)
  76. {
  77.     double tstamp;
  78.  
  79.     GetTimeStamp(hBuff, &tstamp);
  80.     return tstamp - audio_delta;
  81. };
  82.  
  83. int decode_audio(AVCodecContext  *ctx, queue_t *qa)
  84. {
  85.     AVPacket   pkt;
  86.     AVPacket    pkt_tmp;
  87.  
  88.     int         len;
  89.     int         data_size=0;
  90.  
  91.     if( astream.count > AVCODEC_MAX_AUDIO_FRAME_SIZE*7)
  92.         return 1;
  93.  
  94.     if( get_packet(qa, &pkt) == 0 )
  95.         return 0;
  96.  
  97.  //          __asm__("int3");
  98.  
  99.     pkt_tmp = pkt;
  100.  
  101.     while(pkt_tmp.size > 0)
  102.     {
  103.         data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
  104.  
  105.         len = avcodec_decode_audio3(ctx,(int16_t*)decoder_buffer,
  106.                                    &data_size, &pkt_tmp);
  107.  
  108.         if(len >= 0)
  109.         {
  110. //            if(audio_base == -1.0)
  111. //            {
  112. //                if (pkt.pts != AV_NOPTS_VALUE)
  113. //                    audio_base = get_audio_base() * pkt.pts;
  114. //                printf("audio base %f\n", audio_base);                
  115. //            };
  116.            
  117.             pkt_tmp.data += len;
  118.             pkt_tmp.size -= len;
  119.  
  120.             mutex_lock(&astream.lock);
  121.             memcpy(astream.buffer+astream.count, decoder_buffer, data_size);
  122.             astream.count += data_size;
  123.             mutex_unlock(&astream.lock);
  124.        }
  125.        else pkt_tmp.size = 0;
  126.     }
  127.     av_free_packet(&pkt);
  128.     return 1;
  129. };
  130.  
  131.  
  132. static void sync_audio(SNDBUF hbuff, int buffsize)
  133. {
  134.     SND_EVENT   evnt;
  135.     uint32_t    offset;
  136.     double      time_stamp;
  137.  
  138. #ifdef BLACK_MAGIC_SOUND
  139.  
  140.     while( player_state != CLOSED)
  141.     {
  142.         GetNotify(&evnt);
  143.  
  144.         if(evnt.code != 0xFF000001)
  145.         {
  146.             printf("invalid event code %d\n\r", evnt.code);
  147.             continue;
  148.         }
  149.  
  150.         if(evnt.stream != hbuff)
  151.         {
  152.             printf("invalid stream %x hBuff= %x\n\r",
  153.                     evnt.stream, hbuff);
  154.             continue;
  155.         }
  156.  
  157.         GetTimeStamp(hbuff, &time_stamp);
  158.         audio_delta = time_stamp - last_time_stamp;
  159.  
  160.         offset = evnt.offset;
  161.  
  162.         mutex_lock(&astream.lock);
  163.         {
  164.             SetBuffer(hbuff, astream.buffer, offset, buffsize);
  165.             samples_written+= buffsize/4;
  166.             astream.count -= buffsize;
  167.             if(astream.count)
  168.                 memcpy(astream.buffer, astream.buffer+buffsize, astream.count);
  169.             mutex_unlock(&astream.lock);
  170.         };
  171.         break;
  172.     };
  173. #endif
  174.  
  175. };
  176.  
  177.  
  178. int audio_thread(void *param)
  179. {
  180.     SND_EVENT evnt;
  181.  
  182.     int       buffsize;
  183.     int      samples;
  184.     int       err;
  185.     char     *errstr;
  186.     int       active;
  187.  
  188.  
  189.     if((err = CreateBuffer(snd_format|PCM_RING,0, &hBuff)) != 0)
  190.     {
  191.         errstr = "Cannot create sound buffer\n\r";
  192.         goto exit_whith_error;
  193.     };
  194.  
  195.     SetVolume(hBuff,-1000,-1000);
  196.  
  197.     if((err = GetBufferSize(hBuff, &buffsize)) != 0)
  198.     {
  199.         errstr = "Cannot get buffer size\n\r";
  200.         goto exit_whith_error;
  201.     };
  202.  
  203.     buffsize = buffsize/2;
  204.  
  205.     samples = buffsize/4;
  206.  
  207.     while( (astream.count < buffsize*2) &&
  208.                (player_state != CLOSED) )
  209.         yield();
  210.  
  211.     mutex_lock(&astream.lock);
  212.     {
  213.         SetBuffer(hBuff, astream.buffer, 0, buffsize);
  214.         samples_written+= buffsize/4;
  215.         astream.count -= buffsize;
  216.         if(astream.count)
  217.             memcpy(astream.buffer, astream.buffer+buffsize, astream.count);
  218.         mutex_unlock(&astream.lock);
  219.     };
  220.  
  221.     while( player_state != CLOSED)
  222.     {
  223.         uint32_t  offset;
  224.         double    event_stamp, wait_stamp;
  225.         int       too_late = 0;
  226.  
  227.         if((player_state == PAUSE) ||
  228.            (player_state == PLAY_INIT) )
  229.         {
  230.             if( active )
  231.             {
  232.                 StopBuffer(hBuff);
  233.                 active = 0;
  234.             };
  235.             delay(1);
  236.             continue;
  237.         }
  238.         else if(player_state == REWIND)
  239.         {
  240.             if( active )
  241.             {
  242.                 StopBuffer(hBuff);
  243.                 active = 0;
  244.             };
  245.             mutex_lock(&astream.lock);
  246.             astream.count = 0;
  247.             mutex_unlock(&astream.lock);
  248.             delay(1);
  249.             continue;
  250.         }
  251.         else if(player_state == PAUSE_2_PLAY)
  252.         {
  253. //            SetTimeBase(hBuff, audio_base);
  254.             GetTimeStamp(hBuff, &last_time_stamp);
  255. //            printf("last_time_stamp %f\n", last_time_stamp);
  256.            
  257.             if((err = PlayBuffer(hBuff, 0)) !=0 )
  258.             {
  259.                 errstr = "Cannot play buffer\n\r";
  260.                 goto exit_whith_error;
  261.             };
  262.             active = 1;
  263.             sync_audio(hBuff, buffsize);
  264.             player_state = PLAY;
  265.             printf("render: set audio latency to %f\n", audio_delta);
  266.         }
  267.         else if(player_state == REWIND_2_PLAY)
  268.         {
  269.             while( (astream.count < buffsize*2) &&
  270.                    (player_state != CLOSED) )
  271.             yield();
  272.  
  273.             SetTimeBase(hBuff, audio_base);
  274.             GetTimeStamp(hBuff, &last_time_stamp);
  275.             printf("last audio time stamp %f\n", last_time_stamp);
  276.            
  277.             if((err = PlayBuffer(hBuff, 0)) !=0 )
  278.             {
  279.                 errstr = "Cannot play buffer\n\r";
  280.                 goto exit_whith_error;
  281.             };
  282.             active = 1;
  283.             sync_audio(hBuff, buffsize);
  284.             player_state = PLAY;
  285.             printf("render: set audio latency to %f\n", audio_delta);
  286.         };
  287.  
  288.         GetNotify(&evnt);
  289.  
  290.         if(evnt.code != 0xFF000001)
  291.         {
  292.             printf("invalid event code %d\n\r", evnt.code);
  293.             continue;
  294.         }
  295.  
  296.         if(evnt.stream != hBuff)
  297.         {
  298.             printf("invalid stream %x hBuff= %x\n\r",
  299.                     evnt.stream, hBuff);
  300.             continue;
  301.         };
  302.  
  303.         GetTimeStamp(hBuff, &event_stamp);
  304.  
  305.         offset = evnt.offset;
  306.  
  307.         while( (astream.count < buffsize) &&
  308.                (player_state != CLOSED) )
  309.         {
  310.             yield();
  311.             GetTimeStamp(hBuff, &wait_stamp);
  312.             if( (wait_stamp - event_stamp) >
  313.                  samples*1500/sample_rate )
  314.             {
  315.                 samples_lost+= samples;
  316.                 audio_delta = (double)samples_lost*1000/sample_rate;
  317. //                printf("audio delta %f\n", audio_delta);
  318.                 too_late = 1;
  319.                 break;
  320.             }
  321.         };
  322.  
  323.         if((too_late == 1) || (player_state == CLOSED))
  324.         {
  325.             too_late = 0;
  326.             continue;
  327.         };
  328.  
  329.         mutex_lock(&astream.lock);
  330.         SetBuffer(hBuff, astream.buffer, offset, buffsize);
  331.         samples_written+= buffsize/4;
  332.         astream.count -= buffsize;
  333.         if(astream.count)
  334.             memcpy(astream.buffer, astream.buffer+buffsize, astream.count);
  335.         mutex_unlock(&astream.lock);
  336.     }
  337.  
  338.     StopBuffer(hBuff);
  339.     DestroyBuffer(hBuff);
  340.  
  341.     return 0;
  342.  
  343. exit_whith_error:
  344.  
  345.     printf(errstr);
  346.     return -1;
  347.  
  348. };
  349.  
  350.