Support ogg loop playback
[platform/core/multimedia/libmm-sound.git] / server / plugin / ogg / mm_sound_plugin_codec_ogg.c
index 5151aa0..805c7a6 100644 (file)
@@ -90,36 +90,70 @@ typedef struct {
 
 static int (*g_thread_pool_func)(void*, void (*)(void*)) = NULL;
 
+static void _reset_ogg_decoder(ogg_info_t *p)
+{
+       int err, used_size, skipsize;
+       OGG_DEC_INFO ogg_info;
+
+       err = OGGDEC_ResetDecode(p->decoder);
+       if (err != OGGDEC_SUCCESS) {
+               debug_error("Failed to RESET decoder!");
+               return;
+       }
+
+       err = OGGDEC_InitDecode(p->decoder, (unsigned char*)p->source->ptr, p->BufferSize, &skipsize);
+       if (err != OGGDEC_SUCCESS) {
+               debug_error("Failed to INIT decoder!");
+               return;
+       }
+
+       err = OGGDEC_InfoDecode(p->decoder, p->source->ptr + skipsize, &used_size, &ogg_info);
+       if (err != OGGDEC_SUCCESS) {
+               debug_error("Failed to INFO decoder!");
+               return;
+       }
+}
+
 void _pcm_out_func(void *data)
 {
-       ogg_info_t *p = (ogg_info_t*) data;
-       int used_size;
-       int decoded_len;
-       unsigned char* ogg_buf;
-       unsigned int ogg_remain;
-       int err;
+       ogg_info_t *p = (ogg_info_t *)data;
+       int used_size = 0;
+       int decoded_len = 0;
+       unsigned char* ogg_buf = NULL;
+       int err = 0;
 
-       debug_enter("\n");
+       debug_enter();
+
+       if (!p) {
+               debug_error("Invalid ogg_info_t...");
+               return;
+       }
 
        sem_wait(&p->start_wave_signal);
-       ogg_buf = MMSourceGetPtr(p->source);
-       ogg_remain = MMSourceGetCurSize(p->source);
 
-       while (p->state == STATE_PLAY) {
-               err = OGGDEC_FrameDecode(p->decoder, ogg_buf+p->offset, &used_size, p->pcm_out_buf, &decoded_len);
-               if (decoded_len > 0) {
+       while (((p->repeat_count == -1) ? (1) : (p->repeat_count--)) && p->state == STATE_PLAY) {
+               ogg_buf = MMSourceGetPtr(p->source) + p->offset;
+
+               while (p->state == STATE_PLAY) {
+                       decoded_len = 0;
+                       err = OGGDEC_FrameDecode(p->decoder, ogg_buf, &used_size, p->pcm_out_buf, &decoded_len);
+                       if (decoded_len <= 0) {
+                               debug_error("decoded len = %d", decoded_len);
+                               break;
+                       }
+
                        mm_sound_pa_write(p->handle, p->pcm_out_buf, decoded_len);
                        ogg_buf += used_size;
-                       ogg_remain -= used_size;
-                       if(err != OGGDEC_SUCCESS) {
-                               MMSoundPlugCodecOggStop((MMHandleType)p);
-                               debug_error("Decode done :: %d\n", err);
+
+                       if (err != OGGDEC_SUCCESS)
                                break;
-                       }
-               } else {
-                       MMSoundPlugCodecOggStop((MMHandleType)p);
-                       break;
                }
+
+               debug_error("decode done = [%d], repeat_count = [%d]", err, p->repeat_count);
+               if (err == OGGDEC_FAIL || p->repeat_count == 0)
+                       MMSoundPlugCodecOggStop((MMHandleType)p);
+               else
+                       _reset_ogg_decoder(p);
        }
 
        mm_sound_pa_drain(p->handle);
@@ -128,10 +162,10 @@ void _pcm_out_func(void *data)
        /* Notice */
        /* OggDestory is called by stop_cb func */
        /* INDEED the stop_cb must be called, after end of all progress */
-       if(p->stop_cb) {
+       if (p->stop_cb)
                p->stop_cb(p->cb_param);
-       }
-       debug_leave("\n");
+
+       debug_leave();
 }
 
 int MMSoundPlugCodecOggSetThreadPool(int (*func)(void*, void (*)(void*)))