maru_codec : Fixed multi-decoding audio codecs.
authorKitae Kim <kt920.kim@samsung.com>
Mon, 17 Dec 2012 17:14:11 +0000 (02:14 +0900)
committerKitae Kim <kt920.kim@samsung.com>
Mon, 17 Dec 2012 17:14:11 +0000 (02:14 +0900)
Source clean-up and codec device can decode a number of audio codecs concurrently.
As codec device memory region is divided into each 256K size, emulator can decode
64 audio codecs simultaneously.

Signed-off-by: Kitae Kim <kt920.kim@samsung.com>
tizen/src/hw/maru_codec.c
tizen/src/hw/maru_codec.h

index c5c6b19..88451d7 100644 (file)
 
 #include "maru_codec.h"
 #include "qemu-common.h"
+#include "qemu-thread.h"
 
 #define MARU_CODEC_DEV_NAME     "codec"
-#define MARU_CODEC_VERSION      "1.3"
+#define MARU_CODEC_VERSION      13
 
 /*  Needs 16M to support 1920x1080 video resolution.
  *  Output size for encoding has to be greater than (width * height * 6)
@@ -49,11 +50,28 @@ MULTI_DEBUG_CHANNEL(qemu, marucodec);
 
 void codec_thread_init(SVCodecState *s)
 {
+    int index = 0;
+    QemuThread *pthread = NULL;
     TRACE("Enter, %s\n", __func__);
 
-    qemu_thread_create(&s->thread_id, codec_worker_thread, (void *)s,
+    pthread = g_malloc0(sizeof(QemuThread) * CODEC_MAX_THREAD);
+    if (!pthread) {
+        ERR("Failed to allocate wrk_thread memory.\n");
+        return;
+    }
+    qemu_cond_init(&s->codec_thread.cond);
+    qemu_mutex_init(&s->codec_thread.mutex);
+
+    qemu_mutex_lock(&s->thread_mutex);
+    s->isrunning = 1;
+    qemu_mutex_unlock(&s->thread_mutex);
+
+    for (; index < CODEC_MAX_THREAD; index++) {
+        qemu_thread_create(&pthread[index], codec_worker_thread, (void *)s,
             QEMU_THREAD_JOINABLE);
+    }
 
+    s->codec_thread.wrk_thread = pthread;
     TRACE("Leave, %s\n", __func__);
 }
 
@@ -62,10 +80,9 @@ void codec_thread_exit(SVCodecState *s)
     TRACE("Enter, %s\n", __func__);
 
     TRACE("destroy mutex and conditional.\n");
-    qemu_mutex_destroy(&s->thread_mutex);
-    qemu_cond_destroy(&s->thread_cond);
+    qemu_mutex_destroy(&s->codec_thread.mutex);
+    qemu_cond_destroy(&s->codec_thread.cond);
 
-/*  qemu_thread_exit((void*)0); */
     TRACE("Leave, %s\n", __func__);
 }
 
@@ -73,7 +90,7 @@ void wake_codec_worker_thread(SVCodecState *s)
 {
     TRACE("Enter, %s\n", __func__);
 
-    qemu_cond_signal(&s->thread_cond);
+    qemu_cond_signal(&s->codec_thread.cond);
     TRACE("sent a conditional signal to a worker thread.\n");
 
     TRACE("Leave, %s\n", __func__);
@@ -82,18 +99,19 @@ void wake_codec_worker_thread(SVCodecState *s)
 void *codec_worker_thread(void *opaque)
 {
     SVCodecState *s = (SVCodecState *)opaque;
+    QemuThread  thread;
     AVCodecContext *avctx;
 
     TRACE("Enter, %s\n", __func__);
     qemu_mutex_lock(&s->thread_mutex);
 
-    while (1) {
-        TRACE("wait conditional signal.\n");
-        qemu_cond_wait(&s->thread_cond, &s->thread_mutex);
+    while (s->isrunning) {
+        TRACE("wait for conditional signal.\n");
+        qemu_cond_wait(&s->codec_thread.cond, &s->thread_mutex);
 
-        TRACE("wake up a worker thread.\n");
-        avctx = s->ctx_arr[s->codec_param.ctx_index].avctx;
-        /* decode and encode */
+        qemu_thread_get_self(&thread);
+        TRACE("wake up a worker thread. :%x\n", thread.thread);
+        avctx = s->codec_ctx[s->codec_param.ctx_index].avctx;
         if (avctx) {
             if (avctx->codec->decode) {
                 decode_codec(s);
@@ -106,7 +124,7 @@ void *codec_worker_thread(void *opaque)
             continue;
         }
 
-        s->thread_state = CODEC_IRQ;
+        s->codec_thread.state = CODEC_IRQ;
         qemu_bh_schedule(s->tx_bh);
     }
     qemu_mutex_unlock(&s->thread_mutex);
@@ -119,20 +137,18 @@ int decode_codec(SVCodecState *s)
     uint32_t len = 0, ctx_index;
 
     TRACE("Enter, %s\n", __func__);
-    qemu_mutex_unlock(&s->thread_mutex);
-/*  qemu_mutex_lock(&s->thread_mutex); */
 
+    qemu_mutex_lock(&s->codec_thread.mutex);
     ctx_index = s->codec_param.ctx_index;
-    avctx = s->ctx_arr[ctx_index].avctx;
+    qemu_mutex_unlock(&s->codec_thread.mutex);
+
+    avctx = s->codec_ctx[ctx_index].avctx;
     if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
         len = qemu_avcodec_decode_video(s, ctx_index);
     } else {
         len = qemu_avcodec_decode_audio(s, ctx_index);
     }
 
-/*  qemu_mutex_unlock(&s->thread_mutex); */
-    qemu_mutex_lock(&s->thread_mutex);
-
     TRACE("Leave, %s\n", __func__);
     return len;
 }
@@ -145,17 +161,15 @@ int encode_codec(SVCodecState *s)
     TRACE("Enter, %s\n", __func__);
 
     qemu_mutex_unlock(&s->thread_mutex);
-/*  qemu_mutex_lock(&s->thread_mutex); */
 
     ctx_index = s->codec_param.ctx_index;
-    avctx = s->ctx_arr[ctx_index].avctx;
+    avctx = s->codec_ctx[ctx_index].avctx;
     if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
         len = qemu_avcodec_encode_video(s, ctx_index);
     } else {
         len = qemu_avcodec_encode_audio(s, ctx_index);
     }
 
-/*  qemu_mutex_unlock(&s->thread_mutex); */
     qemu_mutex_lock(&s->thread_mutex);
 
     TRACE("Leave, %s\n", __func__);
@@ -282,51 +296,37 @@ void qemu_parser_init(SVCodecState *s, int ctx_index)
 {
     TRACE("[%s] Enter\n", __func__);
 
-    s->ctx_arr[ctx_index].parser_buf = NULL;
-    s->ctx_arr[ctx_index].parser_use = false;
+    s->codec_ctx[ctx_index].parser_buf = NULL;
+    s->codec_ctx[ctx_index].parser_use = false;
 
     TRACE("[%s] Leave\n", __func__);
 }
 
-void qemu_codec_close(SVCodecState *s, uint32_t value)
+void qemu_reset_codec_info(SVCodecState *s, uint32_t value)
 {
     int i;
-    int ctx_index = 0;
+    int ctx_index = 0, mem_index;
 
     TRACE("[%s] Enter\n", __func__);
     qemu_mutex_lock(&s->thread_mutex);
 
-    for (i = 0; i < CODEC_MAX_CONTEXT; i++) {
-        if (s->ctx_arr[i].file_value == value) {
-            ctx_index = i;
+    for (i = 0; i < CODEC_CONTEXT_MAX; i++) {
+        if (s->codec_ctx[i].file_index == value) {
+            TRACE("[%s] close %d context\n", __func__, i);
+            s->codec_ctx[i].avctx_use = false;
             break;
         }
     }
 
-    TRACE("[%s] close %d context\n", __func__, ctx_index);
-    s->ctx_arr[ctx_index].ctx_used = false;
+    mem_index = s->codec_ctx[i].mem_index;
+    s->codec_offset[mem_index] = 0;
+
     qemu_parser_init(s, ctx_index);
 
     qemu_mutex_unlock(&s->thread_mutex);
     TRACE("[%s] Leave\n", __func__);
 }
 
-void qemu_get_codec_ver(SVCodecState *s)
-{
-    char codec_ver[32];
-    off_t offset;
-    int ctx_index;
-
-    offset = s->codec_param.mmap_offset;
-    ctx_index = s->codec_param.ctx_index;
-
-    memset(codec_ver, 0, 32);
-    pstrcpy(codec_ver, sizeof(codec_ver), MARU_CODEC_VERSION);
-
-    TRACE("%d of codec_version:%s\n", ctx_index, codec_ver);
-    memcpy((uint8_t *)s->vaddr + offset, codec_ver, sizeof(codec_ver));
-}
-
 /* void av_register_all() */
 void qemu_av_register_all(void)
 {
@@ -358,7 +358,7 @@ void qemu_avcodec_release_buffer(AVCodecContext *context, AVFrame *picture)
 #endif
 
 /* int avcodec_open(AVCodecContext *avctx, AVCodec *codec) */
-int qemu_avcodec_open(SVCodecState *s, int ctx_index)
+int qemu_avcodec_open(SVCodecState *s)
 {
     AVCodecContext *avctx;
     AVCodec *codec;
@@ -367,18 +367,28 @@ int qemu_avcodec_open(SVCodecState *s, int ctx_index)
     int ret = -1;
     int bEncode = 0;
     int size = 0;
+    int ctx_index = 0;
+
+
+    av_register_all();
+    TRACE("av_register_all\n");
+
+    ctx_index = qemu_avcodec_alloc_context(s);
+    if (ctx_index < 0) {
+        return ret;
+    }
 
     qemu_mutex_lock(&s->thread_mutex);
+    offset = s->codec_param.mmap_offset;
+    qemu_mutex_unlock(&s->thread_mutex);
 
-    avctx = s->ctx_arr[ctx_index].avctx;
+    avctx = s->codec_ctx[ctx_index].avctx;
     if (!avctx) {
         ERR("[%s] %d of AVCodecContext is NULL!\n", __func__, ctx_index);
         qemu_mutex_unlock(&s->thread_mutex);
         return ret;
     }
 
-    offset = s->codec_param.mmap_offset;
-
     TRACE("[%s] Context Index:%d, offset:%d\n", __func__, ctx_index, offset);
     memcpy(&avctx->bit_rate, (uint8_t *)s->vaddr + offset, sizeof(int));
     size = sizeof(int);
@@ -475,8 +485,10 @@ int qemu_avcodec_open(SVCodecState *s, int ctx_index)
               avctx->sample_rate, avctx->channels);
     }
 
-    memcpy((uint8_t *)s->vaddr + offset, &avctx->pix_fmt, sizeof(int));
+    memcpy((uint8_t *)s->vaddr + offset, &ctx_index, sizeof(int));
     size = sizeof(int);
+    memcpy((uint8_t *)s->vaddr + offset + size, &avctx->pix_fmt, sizeof(int));
+    size += sizeof(int);
     size += qemu_serialize_rational(&avctx->time_base,
             (uint8_t *)s->vaddr + offset + size);
     memcpy((uint8_t *)s->vaddr + offset + size, &avctx->channels, sizeof(int));
@@ -509,7 +521,6 @@ int qemu_avcodec_open(SVCodecState *s, int ctx_index)
     memcpy((uint8_t *)s->vaddr + offset + size, &ret, sizeof(int));
     size += sizeof(int);
 
-    qemu_mutex_unlock(&s->thread_mutex);
     TRACE("Leave, %s\n", __func__);
     return ret;
 }
@@ -526,7 +537,7 @@ int qemu_avcodec_close(SVCodecState *s, int ctx_index)
 
     offset = s->codec_param.mmap_offset;
 
-    avctx = s->ctx_arr[ctx_index].avctx;
+    avctx = s->codec_ctx[ctx_index].avctx;
     if (!avctx) {
         ERR("[%s] %d of AVCodecContext is NULL\n", __func__, ctx_index);
         memcpy((uint8_t *)s->vaddr + offset, &ret, sizeof(int));
@@ -546,64 +557,43 @@ int qemu_avcodec_close(SVCodecState *s, int ctx_index)
 }
 
 /* AVCodecContext* avcodec_alloc_context (void) */
-void qemu_avcodec_alloc_context(SVCodecState *s)
+int qemu_avcodec_alloc_context(SVCodecState *s)
 {
     off_t offset;
     int index;
 
     TRACE("[%s] Enter\n", __func__);
-    qemu_mutex_lock(&s->thread_mutex);
 
     offset = s->codec_param.mmap_offset;
 
-    for (index = 0; index < CODEC_MAX_CONTEXT; index++) {
-        if (s->ctx_arr[index].ctx_used == false) {
-            TRACE("[%s] Succeeded to get context[%d].\n", __func__, index);
+    for (index = 0; index < CODEC_CONTEXT_MAX; index++) {
+        if (s->codec_ctx[index].avctx_use == false) {
+            TRACE("Succeeded to get %d of context.\n", index);
             break;
         }
-        TRACE("[%s] Failed to get context[%d].\n", __func__, index);
+        TRACE("Failed to get context.\n");
     }
 
-    if (index == CODEC_MAX_CONTEXT) {
-        ERR("[%s] Failed to get available codec context from now\n", __func__);
-        ERR("[%s] Try to run codec again\n", __func__);
-        qemu_mutex_unlock(&s->thread_mutex);
-        return;
+    if (index == CODEC_CONTEXT_MAX) {
+        ERR("Failed to get available codec context.");
+        ERR(" Try to run codec again.\n");
+        return -1;
     }
 
     TRACE("allocate %d of context and frame.\n", index);
-    s->ctx_arr[index].avctx = avcodec_alloc_context();
-    s->ctx_arr[index].frame = avcodec_alloc_frame();
+    s->codec_ctx[index].avctx = avcodec_alloc_context();
+    s->codec_ctx[index].frame = avcodec_alloc_frame();
 
-    s->ctx_arr[index].file_value = s->codec_param.file_index;
-    s->ctx_arr[index].ctx_used = true;
-    memcpy((uint8_t *)s->vaddr + offset, &index, sizeof(int));
+    s->codec_ctx[index].file_index = s->codec_param.file_index;
+       s->codec_ctx[index].mem_index = s->codec_param.mem_index;
+    s->codec_ctx[index].avctx_use = true;
+//    memcpy((uint8_t *)s->vaddr + offset, &index, sizeof(int));
     qemu_parser_init(s, index);
 
-    qemu_mutex_unlock(&s->thread_mutex);
-
     TRACE("[%s] Leave\n", __func__);
-}
-
-#if 0
-/* AVFrame *avcodec_alloc_frame(void) */
-void qemu_avcodec_alloc_frame(SVCodecState *s, int ctx_index)
-{
-    AVFrame *frame = NULL;
 
-    TRACE("[%s] Enter\n", __func__);
-    qemu_mutex_lock(&s->thread_mutex);
-
-    frame = avcodec_alloc_frame();
-    if (!frame) {
-        ERR("[%s] Failed to allocate frame\n", __func__);
-    }
-    s->ctx_arr[ctx_index].frame = frame;
-
-    qemu_mutex_unlock(&s->thread_mutex);
-    TRACE("[%s] Leave\n", __func__);
+    return index;
 }
-#endif
 
 /* void av_free(void *ptr) */
 void qemu_av_free(SVCodecState *s, int ctx_index)
@@ -614,8 +604,8 @@ void qemu_av_free(SVCodecState *s, int ctx_index)
     TRACE("enter %s\n", __func__);
     qemu_mutex_lock(&s->thread_mutex);
 
-    avctx = s->ctx_arr[ctx_index].avctx;
-    avframe = s->ctx_arr[ctx_index].frame;
+    avctx = s->codec_ctx[ctx_index].avctx;
+    avframe = s->codec_ctx[ctx_index].frame;
 
     if (avctx && avctx->palctrl) {
         av_free(avctx->palctrl);
@@ -631,13 +621,13 @@ void qemu_av_free(SVCodecState *s, int ctx_index)
     if (avctx) {
         TRACE("free codec context\n");
         av_free(avctx);
-        s->ctx_arr[ctx_index].avctx = NULL;
+        s->codec_ctx[ctx_index].avctx = NULL;
     }
 
     if (avframe) {
         TRACE("free codec frame\n");
         av_free(avframe);
-        s->ctx_arr[ctx_index].frame = NULL;
+        s->codec_ctx[ctx_index].frame = NULL;
     }
 
     qemu_mutex_unlock(&s->thread_mutex);
@@ -652,7 +642,7 @@ void qemu_avcodec_flush_buffers(SVCodecState *s, int ctx_index)
     TRACE("Enter\n");
     qemu_mutex_lock(&s->thread_mutex);
 
-    avctx = s->ctx_arr[ctx_index].avctx;
+    avctx = s->codec_ctx[ctx_index].avctx;
     if (avctx) {
         avcodec_flush_buffers(avctx);
     } else {
@@ -682,22 +672,22 @@ int qemu_avcodec_decode_video(SVCodecState *s, int ctx_index)
     off_t offset;
 
     TRACE("Enter, %s\n", __func__);
-    qemu_mutex_lock(&s->thread_mutex);
+    qemu_mutex_lock(&s->codec_thread.mutex);
 
     TRACE("[%s] Video Context Index : %d\n", __func__, ctx_index);
 
-    avctx = s->ctx_arr[ctx_index].avctx;
-    picture = s->ctx_arr[ctx_index].frame;
+    avctx = s->codec_ctx[ctx_index].avctx;
+    picture = s->codec_ctx[ctx_index].frame;
     if (!avctx || !picture) {
         ERR("[%s] %d of Context or Frame is NULL!\n", __func__, ctx_index);
-        qemu_mutex_unlock(&s->thread_mutex);
+        qemu_mutex_unlock(&s->codec_thread.mutex);
         return ret;
     }
 
     offset = s->codec_param.mmap_offset;
 
-    parser_buf = s->ctx_arr[ctx_index].parser_buf;
-    parser_use = s->ctx_arr[ctx_index].parser_use;
+    parser_buf = s->codec_ctx[ctx_index].parser_buf;
+    parser_use = s->codec_ctx[ctx_index].parser_use;
     TRACE("[%s] Parser Buffer : %p, Parser:%d\n", __func__,
             parser_buf, parser_use);
 
@@ -716,8 +706,6 @@ int qemu_avcodec_decode_video(SVCodecState *s, int ctx_index)
         buf = parser_buf;
     } else if (buf_size > 0) {
         TRACE("[%s] not use parser, codec_id:%x\n", __func__, avctx->codec_id);
-/*      buf = av_mallocz(buf_size);
-        memcpy(buf, (uint8_t *)s->vaddr + offset + size, buf_size); */
         buf = (uint8_t *)s->vaddr + offset + size;
         size += buf_size;
     } else {
@@ -744,11 +732,6 @@ int qemu_avcodec_decode_video(SVCodecState *s, int ctx_index)
 
     memcpy((uint8_t *)s->vaddr + offset, &avctx->pix_fmt, sizeof(int));
     size = sizeof(int);
-#if 0
-    memcpy((uint8_t *)s->vaddr + offset + size,
-            &avctx->time_base, sizeof(AVRational));
-    size += sizeof(AVRational);
-#endif
     size += qemu_serialize_rational(&avctx->time_base,
                                     (uint8_t *)s->vaddr + offset + size);
     memcpy((uint8_t *)s->vaddr + offset + size, &avctx->width, sizeof(int));
@@ -761,11 +744,6 @@ int qemu_avcodec_decode_video(SVCodecState *s, int ctx_index)
     memcpy((uint8_t *)s->vaddr + offset + size,
             &avctx->frame_number, sizeof(int));
     size += sizeof(int);
-#if 0
-    memcpy((uint8_t *)s->vaddr + offset + size,
-            &avctx->sample_aspect_ratio, sizeof(AVRational));
-    size += sizeof(AVRational);
-#endif
     size += qemu_serialize_rational(&avctx->sample_aspect_ratio,
                                     (uint8_t *)s->vaddr + offset + size);
     memcpy((uint8_t *)s->vaddr + offset + size,
@@ -786,18 +764,16 @@ int qemu_avcodec_decode_video(SVCodecState *s, int ctx_index)
     memcpy((uint8_t *)s->vaddr + offset + size, dst.data[0], numbytes);
     av_free(buffer);
 
-/*    av_free(buf); */
-
     if (parser_buf && parser_use) {
         TRACE("[%s] Free input buffer after decoding video\n", __func__);
         TRACE("[%s] input buffer : %p, %p\n",
             __func__, avpkt.data, parser_buf);
         av_free(avpkt.data);
-        s->ctx_arr[ctx_index].parser_buf = NULL;
+        s->codec_ctx[ctx_index].parser_buf = NULL;
     }
 #endif
 
-    qemu_mutex_unlock(&s->thread_mutex);
+    qemu_mutex_unlock(&s->codec_thread.mutex);
     TRACE("Leave, %s\n", __func__);
 
     return ret;
@@ -819,10 +795,10 @@ int qemu_avcodec_encode_video(SVCodecState *s, int ctx_index)
     off_t offset;
 
     TRACE("Enter, %s\n", __func__);
-    qemu_mutex_lock(&s->thread_mutex);
+    qemu_mutex_lock(&s->codec_thread.mutex);
 
-    avctx = s->ctx_arr[ctx_index].avctx;
-    pict = s->ctx_arr[ctx_index].frame;
+    avctx = s->codec_ctx[ctx_index].avctx;
+    pict = s->codec_ctx[ctx_index].frame;
     if (!avctx || !pict) {
         ERR("[%s] %d of Context or Frame is NULL\n", __func__, ctx_index);
         qemu_mutex_unlock(&s->thread_mutex);
@@ -873,7 +849,7 @@ int qemu_avcodec_encode_video(SVCodecState *s, int ctx_index)
 
     memcpy((uint8_t *)s->vaddr + offset + outbufSize, &ret, sizeof(int));
 
-    qemu_mutex_unlock(&s->thread_mutex);
+    qemu_mutex_unlock(&s->codec_thread.mutex);
     TRACE("Leave, %s\n", __func__);
 
     return ret;
@@ -898,29 +874,32 @@ int qemu_avcodec_decode_audio(SVCodecState *s, int ctx_index)
     off_t offset;
 
     TRACE("Enter, %s\n", __func__);
-    qemu_mutex_lock(&s->thread_mutex);
 
     TRACE("Audio Context Index : %d\n", ctx_index);
-    avctx = s->ctx_arr[ctx_index].avctx;
+    avctx = s->codec_ctx[ctx_index].avctx;
     if (!avctx) {
         ERR("[%s] %d of Context is NULL!\n", __func__, ctx_index);
-        qemu_mutex_unlock(&s->thread_mutex);
+        qemu_mutex_unlock(&s->codec_thread.mutex);
         return ret;
     }
 
     if (!avctx->codec) {
         ERR("[%s] %d of Codec is NULL\n", __func__, ctx_index);
-        qemu_mutex_unlock(&s->thread_mutex);
+        qemu_mutex_unlock(&s->codec_thread.mutex);
         return ret;
     }
 
     offset = s->codec_param.mmap_offset;
 
-    parser_buf = s->ctx_arr[ctx_index].parser_buf;
-    parser_use = s->ctx_arr[ctx_index].parser_use;
+    parser_buf = s->codec_ctx[ctx_index].parser_buf;
+    parser_use = s->codec_ctx[ctx_index].parser_use;
 
     memcpy(&buf_size, (uint8_t *)s->vaddr + offset, sizeof(int));
     size = sizeof(int);
+    memcpy(&avctx->channel_layout, (uint8_t *)s->vaddr + offset, sizeof(int64_t));
+    size += sizeof(int64_t);
+    memcpy(&avctx->request_channel_layout, (uint8_t *)s->vaddr + offset, sizeof(int64_t));
+    size += sizeof(int64_t);
     TRACE("input buffer size : %d\n", buf_size);
 
     if (parser_buf && parser_use) {
@@ -950,7 +929,7 @@ int qemu_avcodec_decode_audio(SVCodecState *s, int ctx_index)
     memcpy((uint8_t *)s->vaddr + offset, &avctx->bit_rate, sizeof(int));
     size = sizeof(int);
     memcpy((uint8_t *)s->vaddr + offset + size,
-                       &avctx->sample_rate, sizeof(int));
+            &avctx->sample_rate, sizeof(int));
     size += sizeof(int);
     memcpy((uint8_t *)s->vaddr + offset + size, &avctx->channels, sizeof(int));
     size += sizeof(int);
@@ -978,10 +957,9 @@ int qemu_avcodec_decode_audio(SVCodecState *s, int ctx_index)
     if (parser_buf && parser_use) {
         TRACE("[%s] free parser buf\n", __func__);
         av_free(avpkt.data);
-        s->ctx_arr[ctx_index].parser_buf = NULL;
+        s->codec_ctx[ctx_index].parser_buf = NULL;
     }
 
-    qemu_mutex_unlock(&s->thread_mutex);
     TRACE("[%s] Leave\n", __func__);
 
     return ret;
@@ -1009,8 +987,8 @@ void qemu_av_picture_copy(SVCodecState *s, int ctx_index)
     TRACE("Enter :%s\n", __func__);
     qemu_mutex_lock(&s->thread_mutex);
 
-    avctx = s->ctx_arr[ctx_index].avctx;
-    src = (AVPicture *)s->ctx_arr[ctx_index].frame;
+    avctx = s->codec_ctx[ctx_index].avctx;
+    src = (AVPicture *)s->codec_ctx[ctx_index].frame;
     if (!avctx && !src) {
         ERR("[%s] %d of context or frame is NULL\n", __func__, ctx_index);
         qemu_mutex_unlock(&s->thread_mutex);
@@ -1057,7 +1035,7 @@ void qemu_av_parser_init(SVCodecState *s, int ctx_index)
     TRACE("Enter :%s\n", __func__);
     qemu_mutex_lock(&s->thread_mutex);
 
-    avctx = s->ctx_arr[ctx_index].avctx;
+    avctx = s->codec_ctx[ctx_index].avctx;
     if (!avctx) {
         ERR("[%s] %d of AVCodecContext is NULL!!\n", __func__, ctx_index);
         qemu_mutex_unlock(&s->thread_mutex);
@@ -1070,12 +1048,12 @@ void qemu_av_parser_init(SVCodecState *s, int ctx_index)
     parser_ctx = av_parser_init(avctx->codec_id);
     if (parser_ctx) {
         TRACE("[%s] using parser\n", __func__);
-        s->ctx_arr[ctx_index].parser_use = true;
+        s->codec_ctx[ctx_index].parser_use = true;
     } else {
         TRACE("[%s] no parser\n", __func__);
-        s->ctx_arr[ctx_index].parser_use = false;
+        s->codec_ctx[ctx_index].parser_use = false;
     }
-    s->ctx_arr[ctx_index].parser_ctx = parser_ctx;
+    s->codec_ctx[ctx_index].parser_ctx = parser_ctx;
 
     qemu_mutex_unlock(&s->thread_mutex);
     TRACE("[%s] Leave\n", __func__);
@@ -1103,8 +1081,8 @@ int qemu_av_parser_parse(SVCodecState *s, int ctx_index)
     TRACE("Enter %s\n", __func__);
     qemu_mutex_lock(&s->thread_mutex);
 
-    parser_ctx = s->ctx_arr[ctx_index].parser_ctx;
-    avctx = s->ctx_arr[ctx_index].avctx;
+    parser_ctx = s->codec_ctx[ctx_index].parser_ctx;
+    avctx = s->codec_ctx[ctx_index].avctx;
     if (!avctx) {
         ERR("[%s] %d of AVCodecContext is NULL\n", __func__, ctx_index);
         qemu_mutex_unlock(&s->thread_mutex);
@@ -1151,7 +1129,7 @@ int qemu_av_parser_parse(SVCodecState *s, int ctx_index)
     TRACE("after parsing, outbuf size :%d, ret:%d\n", poutbuf_size, ret);
 
     if (poutbuf) {
-        s->ctx_arr[ctx_index].parser_buf = poutbuf;
+        s->codec_ctx[ctx_index].parser_buf = poutbuf;
     }
 
     TRACE("[%s] inbuf : %p, outbuf : %p\n", __func__, inbuf, poutbuf);
@@ -1188,7 +1166,7 @@ void qemu_av_parser_close(SVCodecState *s, int ctx_index)
     TRACE("Enter, %s\n", __func__);
     qemu_mutex_lock(&s->thread_mutex);
 
-    parser_ctx = s->ctx_arr[ctx_index].parser_ctx;
+    parser_ctx = s->codec_ctx[ctx_index].parser_ctx;
     if (!parser_ctx) {
         ERR("AVCodecParserContext is NULL\n");
         qemu_mutex_unlock(&s->thread_mutex);
@@ -1211,46 +1189,21 @@ int codec_operate(uint32_t api_index, uint32_t ctx_index, SVCodecState *s)
         qemu_av_register_all();
         break;
     case EMUL_AVCODEC_OPEN:
-        ret = qemu_avcodec_open(s, ctx_index);
+        ret = qemu_avcodec_open(s);
         break;
     case EMUL_AVCODEC_CLOSE:
         ret = qemu_avcodec_close(s, ctx_index);
-        break;
-    case EMUL_AVCODEC_ALLOC_CONTEXT:
-        qemu_avcodec_alloc_context(s);
-        break;
-#if 0
-    case EMUL_AVCODEC_ALLOC_FRAME:
-        qemu_avcodec_alloc_frame(s, ctx_index);
-        break;
-#endif
-    case EMUL_AV_FREE:
         qemu_av_free(s, ctx_index);
         break;
     case EMUL_AVCODEC_FLUSH_BUFFERS:
         qemu_avcodec_flush_buffers(s, ctx_index);
         break;
-#ifndef CODEC_THREAD
     case EMUL_AVCODEC_DECODE_VIDEO:
     case EMUL_AVCODEC_ENCODE_VIDEO:
     case EMUL_AVCODEC_DECODE_AUDIO:
     case EMUL_AVCODEC_ENCODE_AUDIO:
         wake_codec_worker_thread(s);
         break;
-#else
-    case EMUL_AVCODEC_DECODE_VIDEO:
-        ret = qemu_avcodec_decode_video(s, ctx_index);
-        break;
-    case EMUL_AVCODEC_ENCODE_VIDEO:
-        ret = qemu_avcodec_encode_video(s, ctx_index);
-        break;
-    case EMUL_AVCODEC_DECODE_AUDIO:
-        ret = qemu_avcodec_decode_audio(s, ctx_index);
-        break;
-    case EMUL_AVCODEC_ENCODE_AUDIO:
-        ret = qemu_avcodec_encode_audio(s, ctx_index);
-        break;
-#endif
     case EMUL_AV_PICTURE_COPY:
         qemu_av_picture_copy(s, ctx_index);
         break;
@@ -1263,15 +1216,26 @@ int codec_operate(uint32_t api_index, uint32_t ctx_index, SVCodecState *s)
     case EMUL_AV_PARSER_CLOSE:
         qemu_av_parser_close(s, ctx_index);
         break;
-    case EMUL_GET_CODEC_VER:
-        qemu_get_codec_ver(s);
-        break;
     default:
         WARN("api index %d does not exist!.\n", api_index);
     }
     return ret;
 }
 
+static uint32_t qemu_get_mmap_offset (SVCodecState *s)
+{
+       int index = 0;
+
+       for (; index < AUDIO_CODEC_MEM_OFFSET_MAX; index++)  {
+               if (s->codec_offset[index] == 0) {
+                       s->codec_offset[index] = 1;
+                       break;
+               }
+       }
+
+       return index;
+}
+
 /*
  *  Codec Device APIs
  */
@@ -1281,14 +1245,32 @@ uint64_t codec_read(void *opaque, target_phys_addr_t addr, unsigned size)
     uint64_t ret = 0;
 
     switch (addr) {
-    case CODEC_QUERY_STATE:
-        ret = s->thread_state;
-        s->thread_state = 0;
-        TRACE("thread state: %d\n", s->thread_state);
+    case CODEC_CMD_GET_THREAD_STATE:
+        qemu_mutex_lock(&s->thread_mutex);
+        ret = s->codec_thread.state;
+        s->codec_thread.state = 0;
+        qemu_mutex_unlock(&s->thread_mutex);
+        TRACE("ret: %d, thread state: %d\n", ret, s->codec_thread.state);
         qemu_irq_lower(s->dev.irq[0]);
         break;
+    case CODEC_CMD_GET_VERSION:
+        ret = MARU_CODEC_VERSION;
+        TRACE("codec version: %d\n", ret);
+        break;
+    case CODEC_CMD_GET_DEVICE_MEM:
+        qemu_mutex_lock(&s->thread_mutex);
+        ret = s->device_mem_avail;
+        if (s->device_mem_avail != 1) {
+            s->device_mem_avail = 1;
+        }
+        qemu_mutex_unlock(&s->thread_mutex);
+        break;
+    case CODEC_CMD_GET_MMAP_OFFSET:
+               ret = qemu_get_mmap_offset(s);
+               INFO("mem index: %d\n", ret);
+               break;
     default:
-        ERR("There is no avaiable command for %s\n", MARU_CODEC_DEV_NAME);
+        ERR("no avaiable command for read. %d\n", addr);
     }
 
     return ret;
@@ -1300,29 +1282,37 @@ void codec_write(void *opaque, target_phys_addr_t addr,
     int ret = -1;
     SVCodecState *s = (SVCodecState *)opaque;
 
-/*  qemu_mutex_lock(&s->thread_mutex); */
     switch (addr) {
-    case CODEC_API_INDEX:
+    case CODEC_CMD_API_INDEX:
         ret = codec_operate(value, s->codec_param.ctx_index, s);
         break;
-    case CODEC_CONTEXT_INDEX:
+    case CODEC_CMD_CONTEXT_INDEX:
         s->codec_param.ctx_index = value;
         TRACE("Context Index: %d\n", s->codec_param.ctx_index);
         break;
-    case CODEC_MMAP_OFFSET:
+    case CODEC_CMD_FILE_INDEX:
+        s->codec_param.file_index = value;
+        break;
+    case CODEC_CMD_DEVICE_MEM_OFFSET:
         s->codec_param.mmap_offset = value;
         TRACE("MMAP Offset: %d\n", s->codec_param.mmap_offset);
         break;
-    case CODEC_FILE_INDEX:
-        s->codec_param.file_index = value;
+    case CODEC_CMD_RESET_CODEC_INFO:
+        qemu_reset_codec_info(s, value);
         break;
-    case CODEC_CLOSED:
-        qemu_codec_close(s, value);
+    case CODEC_CMD_SET_DEVICE_MEM:
+        qemu_mutex_lock(&s->thread_mutex);
+        s->device_mem_avail = value;
+        printf("set device_mem: %d\n", value);
+        qemu_mutex_unlock(&s->thread_mutex);
         break;
+       case CODEC_CMD_SET_MMAP_OFFSET:
+        printf("set mem index: %d\n", value);
+               s->codec_param.mem_index = value;
+               break;
     default:
-        ERR("There is no avaiable command for %s\n", MARU_CODEC_DEV_NAME);
+        ERR("no avaiable command for write. %d\n", addr);
     }
-/*  qemu_mutex_unlock(&s->thread_mutex); */
 }
 
 static const MemoryRegionOps codec_mmio_ops = {
@@ -1339,17 +1329,15 @@ static void codec_tx_bh(void *opaque)
     AVCodecContext *ctx;
 
     ctx_index = s->codec_param.ctx_index;
-    ctx = s->ctx_arr[ctx_index].avctx;
+    ctx = s->codec_ctx[ctx_index].avctx;
 
     TRACE("Enter, %s\n", __func__);
 
     /* raise irq as soon as a worker thread had finished a job*/
-    if (s->thread_state) {
+    if (s->codec_thread.state) {
         TRACE("raise codec irq. state:%d, codec:%d\n",
-                s->thread_state, ctx->codec_type);
+              s->codec_thread.state, ctx->codec_type);
         qemu_irq_raise(s->dev.irq[0]);
-/*      s->thread_state = 0;
-        qemu_bh_schedule(s->tx_bh); */
     }
 
     TRACE("Leave, %s\n", __func__);
@@ -1363,15 +1351,10 @@ static int codec_initfn(PCIDevice *dev)
     INFO("[%s] device init\n", __func__);
 
     memset(&s->codec_param, 0, sizeof(SVCodecParam));
-/*    pthread_mutex_init(&s->codec_mutex, NULL); */
-#ifndef CODEC_THREAD
-    qemu_mutex_init(&s->thread_mutex);
-    qemu_cond_init(&s->thread_cond);
 
+    qemu_mutex_init(&s->thread_mutex);
     codec_thread_init(s);
-
     s->tx_bh = qemu_bh_new(codec_tx_bh, s);
-#endif
 
     pci_config_set_interrupt_pin(pci_conf, 1);
 
index b564b8e..25e1bdc 100644 (file)
 
 #include <libavformat/avformat.h>
 
-#define CODEC_MAX_CONTEXT   1024
-#define CODEC_COPY_DATA
+#define CODEC_CONTEXT_MAX                      1024
+#define VIDEO_CODEC_MEM_OFFSET_MAX     16
+#define AUDIO_CODEC_MEM_OFFSET_MAX     64
+
+#define CODEC_MAX_THREAD       10
 
 /*
  *  Codec Device Structures
@@ -50,6 +53,7 @@ typedef struct _SVCodecParam {
     uint32_t        api_index;
     uint32_t        ctx_index;
     uint32_t        file_index;
+    uint32_t        mem_index;
     uint32_t        mmap_offset;
 } SVCodecParam;
 
@@ -58,42 +62,56 @@ typedef struct _SVCodecContext {
     AVFrame                 *frame;
     AVCodecParserContext    *parser_ctx;
     uint8_t                 *parser_buf;
-    bool                    parser_use;
-    bool                    ctx_used;
-    uint32_t                file_value;
+    uint8_t                 parser_use;
+    uint8_t                 avctx_use;
+    uint32_t                file_index;
+       uint32_t                                mem_index;
 } SVCodecContext;
 
+typedef struct _SVCodecThreadPool {
+       QemuThread                      *wrk_thread;
+       QemuMutex                       mutex;
+       QemuCond                        cond;
+       uint32_t                        state;
+       uint8_t                         isrunning;
+} SVCodecThreadPool;
+
 typedef struct _SVCodecState {
     PCIDevice           dev;
-    SVCodecContext      ctx_arr[CODEC_MAX_CONTEXT];
-    SVCodecParam        codec_param;
 
     uint8_t             *vaddr;
     MemoryRegion        vram;
     MemoryRegion        mmio;
 
     QEMUBH              *tx_bh;
-    QemuThread          thread_id;
     QemuMutex           thread_mutex;
-    QemuCond            thread_cond;
-    uint8_t             thread_state;
+
+    SVCodecContext      codec_ctx[CODEC_CONTEXT_MAX];
+    SVCodecParam        codec_param;
+       SVCodecThreadPool       codec_thread;
+       uint8_t                         codec_offset[AUDIO_CODEC_MEM_OFFSET_MAX];
+       uint8_t                         device_mem_avail;
+       uint8_t                         isrunning;
 } SVCodecState;
 
-enum {
-    CODEC_API_INDEX         = 0x00,
-    CODEC_QUERY_STATE       = 0x04,
-    CODEC_CONTEXT_INDEX     = 0x08,
-    CODEC_MMAP_OFFSET       = 0x0c,
-    CODEC_FILE_INDEX        = 0x10,
-    CODEC_CLOSED            = 0x14,
+enum codec_io_cmd {
+    CODEC_CMD_API_INDEX         = 0x00,
+    CODEC_CMD_CONTEXT_INDEX     = 0x04,
+       CODEC_CMD_FILE_INDEX            = 0x08,
+    CODEC_CMD_DEVICE_MEM_OFFSET        = 0x0c,
+    CODEC_CMD_GET_THREAD_STATE = 0x10,
+    CODEC_CMD_GET_VERSION       = 0x14,
+    CODEC_CMD_GET_DEVICE_MEM    = 0x18,
+    CODEC_CMD_SET_DEVICE_MEM   = 0x1C,
+    CODEC_CMD_GET_MMAP_OFFSET  = 0x20,
+    CODEC_CMD_SET_MMAP_OFFSET  = 0x24,
+    CODEC_CMD_RESET_CODEC_INFO  = 0x28,
 };
 
 enum {
     EMUL_AV_REGISTER_ALL = 1,
-    EMUL_AVCODEC_ALLOC_CONTEXT,
     EMUL_AVCODEC_OPEN,
     EMUL_AVCODEC_CLOSE,
-    EMUL_AV_FREE,
     EMUL_AVCODEC_FLUSH_BUFFERS,
     EMUL_AVCODEC_DECODE_VIDEO,
     EMUL_AVCODEC_ENCODE_VIDEO,
@@ -103,7 +121,6 @@ enum {
     EMUL_AV_PARSER_INIT,
     EMUL_AV_PARSER_PARSE,
     EMUL_AV_PARSER_CLOSE,
-    EMUL_GET_CODEC_VER = 50,
 };
 
 
@@ -139,9 +156,9 @@ void qemu_get_codec_ver(SVCodecState *s);
  *  FFMPEG Functions
  */
 void qemu_av_register_all(void);
-int qemu_avcodec_open(SVCodecState *s, int ctx_index);
+int qemu_avcodec_open(SVCodecState *s);
 int qemu_avcodec_close(SVCodecState *s, int ctx_index);
-void qemu_avcodec_alloc_context(SVCodecState *s);
+int qemu_avcodec_alloc_context(SVCodecState *s);
 void qemu_avcodec_flush_buffers(SVCodecState *s, int ctx_index);
 int qemu_avcodec_decode_video(SVCodecState *s, int ctx_index);
 int qemu_avcodec_encode_video(SVCodecState *s, int ctx_index);