Subversion Repositories Kolibri OS

Rev

Rev 2415 | 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.  
  29. int init_audio(int format)
  30. {
  31.     int    err;
  32.     int    version =-1;
  33.     char  *errstr;
  34.  
  35.     mutex_lock(&driver_lock);
  36.  
  37.     if((err = InitSound(&version)) !=0 )
  38.     {
  39.         mutex_unlock(&driver_lock);
  40.         errstr = "Sound service not installed\n\r";
  41.         goto exit_whith_error;
  42.     };
  43.  
  44.     mutex_unlock(&driver_lock);
  45.  
  46.     printf("sound version 0x%x\n", version);
  47.  
  48.     if( (SOUND_VERSION>(version&0xFFFF)) ||
  49.         (SOUND_VERSION<(version >> 16)))
  50.     {
  51.         errstr = "Sound service version mismatch\n\r";
  52.         goto exit_whith_error;
  53.     }
  54.  
  55.     snd_format = format;
  56.  
  57.     create_thread(audio_thread, 0, 163840);
  58.  
  59.     return 1;
  60.  
  61. exit_whith_error:
  62.  
  63.     printf(errstr);
  64.     return 0;
  65. };
  66.  
  67. static uint64_t samples_lost;
  68. static double  audio_delta;
  69. static double  last_time_stamp;
  70.  
  71.  
  72. double get_master_clock(void)
  73. {
  74.     double tstamp;
  75.  
  76.     GetTimeStamp(hBuff, &tstamp);
  77.     return tstamp - audio_delta;
  78. };
  79.  
  80. int decode_audio(AVCodecContext  *ctx, queue_t *qa)
  81. {
  82.     AVPacket   pkt;
  83.     AVPacket    pkt_tmp;
  84.  
  85.     int         len;
  86.     int         data_size=0;
  87.  
  88.     if( astream.count > AVCODEC_MAX_AUDIO_FRAME_SIZE*7)
  89.         return 1;
  90.  
  91.     if( get_packet(qa, &pkt) == 0 )
  92.         return 0;
  93.  
  94.  //          __asm__("int3");
  95.  
  96.     pkt_tmp = pkt;
  97.  
  98.     while(pkt_tmp.size > 0)
  99.     {
  100.         data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
  101.  
  102.         len = avcodec_decode_audio3(ctx,(int16_t*)decoder_buffer,
  103.                                    &data_size, &pkt_tmp);
  104.  
  105.         if(len >= 0)
  106.         {
  107.             pkt_tmp.data += len;
  108.             pkt_tmp.size -= len;
  109.  
  110.             mutex_lock(&astream.lock);
  111.             memcpy(astream.buffer+astream.count, decoder_buffer, data_size);
  112.             astream.count += data_size;
  113.             mutex_unlock(&astream.lock);
  114.        }
  115.        else pkt_tmp.size = 0;
  116.     }
  117.     av_free_packet(&pkt);
  118.     return 1;
  119. };
  120.  
  121.  
  122. static void sync_audio(SNDBUF hbuff, int buffsize)
  123. {
  124.     SND_EVENT   evnt;
  125.     uint32_t    offset;
  126.     double      time_stamp;
  127.  
  128. #ifdef BLACK_MAGIC_SOUND
  129.  
  130.     while( player_state != CLOSED)
  131.     {
  132.         GetNotify(&evnt);
  133.  
  134.         if(evnt.code != 0xFF000001)
  135.         {
  136.             printf("invalid event code %d\n\r", evnt.code);
  137.             continue;
  138.         }
  139.  
  140.         if(evnt.stream != hbuff)
  141.         {
  142.             printf("invalid stream %x hBuff= %x\n\r",
  143.                     evnt.stream, hbuff);
  144.             continue;
  145.         }
  146.  
  147.         GetTimeStamp(hbuff, &time_stamp);
  148.         audio_delta = time_stamp - last_time_stamp;
  149.  
  150.         offset = evnt.offset;
  151.  
  152.         mutex_lock(&astream.lock);
  153.         {
  154.             SetBuffer(hbuff, astream.buffer, offset, buffsize);
  155.             samples_written+= buffsize/4;
  156.             astream.count -= buffsize;
  157.             if(astream.count)
  158.                 memcpy(astream.buffer, astream.buffer+buffsize, astream.count);
  159.             mutex_unlock(&astream.lock);
  160.         };
  161.         break;
  162.     };
  163. #endif
  164.  
  165. };
  166.  
  167.  
  168. int audio_thread(void *param)
  169. {
  170.     SND_EVENT evnt;
  171.  
  172.     int       buffsize;
  173.     int      samples;
  174.     int       err;
  175.     char     *errstr;
  176.     int       active;
  177.  
  178.  
  179.     if((err = CreateBuffer(snd_format|PCM_RING,0, &hBuff)) != 0)
  180.     {
  181.         errstr = "Cannot create sound buffer\n\r";
  182.         goto exit_whith_error;
  183.     };
  184.  
  185.     SetVolume(hBuff,-1000,-1000);
  186.  
  187.     if((err = GetBufferSize(hBuff, &buffsize)) != 0)
  188.     {
  189.         errstr = "Cannot get buffer size\n\r";
  190.         goto exit_whith_error;
  191.     };
  192.  
  193.     buffsize = buffsize/2;
  194.  
  195.     samples = buffsize/4;
  196.  
  197.     while( (astream.count < buffsize*2) &&
  198.                (player_state != CLOSED) )
  199.         yield();
  200.  
  201.     mutex_lock(&astream.lock);
  202.     {
  203.         SetBuffer(hBuff, astream.buffer, 0, buffsize);
  204.         samples_written+= buffsize/4;
  205.         astream.count -= buffsize;
  206.         if(astream.count)
  207.             memcpy(astream.buffer, astream.buffer+buffsize, astream.count);
  208.         mutex_unlock(&astream.lock);
  209.     };
  210.  
  211.     while( player_state != CLOSED)
  212.     {
  213.         uint32_t  offset;
  214.         double    event_stamp, wait_stamp;
  215.         int       too_late = 0;
  216.  
  217.         if(player_state == PAUSE)
  218.         {
  219.             if( active )
  220.             {
  221.                 StopBuffer(hBuff);
  222.                 active = 0;
  223.             }
  224.             delay(1);
  225.             continue;
  226.         }
  227.         else if(player_state == PLAY_RESTART)
  228.         {
  229.             GetTimeStamp(hBuff, &last_time_stamp);
  230.             if((err = PlayBuffer(hBuff, 0)) !=0 )
  231.             {
  232.                 errstr = "Cannot play buffer\n\r";
  233.                 goto exit_whith_error;
  234.             };
  235.             active = 1;
  236.             sync_audio(hBuff, buffsize);
  237.             player_state = PLAY;
  238.             printf("audio delta %f\n", audio_delta);
  239.         };
  240.  
  241.         GetNotify(&evnt);
  242.  
  243.         if(evnt.code != 0xFF000001)
  244.         {
  245.             printf("invalid event code %d\n\r", evnt.code);
  246.             continue;
  247.         }
  248.  
  249.         if(evnt.stream != hBuff)
  250.         {
  251.             printf("invalid stream %x hBuff= %x\n\r",
  252.                     evnt.stream, hBuff);
  253.             continue;
  254.         };
  255.  
  256.         GetTimeStamp(hBuff, &event_stamp);
  257.  
  258.         offset = evnt.offset;
  259.  
  260.         while( (astream.count < buffsize) &&
  261.                (player_state != CLOSED) )
  262.         {
  263.             yield();
  264.             GetTimeStamp(hBuff, &wait_stamp);
  265.             if( (wait_stamp - event_stamp) >
  266.                  samples*1500/sample_rate )
  267.             {
  268.                 samples_lost+= samples;
  269.                 audio_delta = (double)samples_lost*1000/sample_rate;
  270. //                printf("audio delta %f\n", audio_delta);
  271.                 too_late = 1;
  272.                 break;
  273.             }
  274.         };
  275.  
  276.         if((too_late == 1) || (player_state == CLOSED))
  277.         {
  278.             too_late = 0;
  279.             continue;
  280.         };
  281.  
  282.         mutex_lock(&astream.lock);
  283.         SetBuffer(hBuff, astream.buffer, offset, buffsize);
  284.         samples_written+= buffsize/4;
  285.         astream.count -= buffsize;
  286.         if(astream.count)
  287.             memcpy(astream.buffer, astream.buffer+buffsize, astream.count);
  288.         mutex_unlock(&astream.lock);
  289.     }
  290.  
  291.     StopBuffer(hBuff);
  292.     DestroyBuffer(hBuff);
  293.  
  294.     return 0;
  295.  
  296. exit_whith_error:
  297.  
  298.     printf(errstr);
  299.     return -1;
  300.  
  301. };
  302.  
  303.