brillcodec: add profile module for decoding fps/latency. 43/31343/1
authorgunsoo83.kim <gunsoo83.kim@samsung.com>
Thu, 4 Dec 2014 07:30:28 +0000 (16:30 +0900)
committergunsoo83.kim <gunsoo83.kim@samsung.com>
Thu, 4 Dec 2014 07:37:19 +0000 (16:37 +0900)
- To profile codec performance in device layer,
  add profile module to brillcodec device.

Change-Id: I1c476927afe69dbac76d6091f7f8c9810d85c691
Signed-off-by: gunsoo83.kim <gunsoo83.kim@samsung.com>
tizen/src/hw/pci/maru_brillcodec.c
tizen/src/hw/pci/maru_brillcodec.h
tizen/src/hw/pci/maru_brillcodec_device.c

index db7a6e8ac6eb51e21d7e60d386b8f46a64b0aba5..5b0d1e97d33beb747c6c3fa55f4ebb5acdc67be0 100644 (file)
@@ -57,6 +57,129 @@ MULTI_DEBUG_CHANNEL(qemu, brillcodec);
 // misc
 #define OFFSET_PICTURE_BUFFER (0x100)
 
+// for profile
+#include <glib.h>
+
+static GTimer* profile_decode_timer = NULL;
+static GTimer* profile_copy_timer = NULL;
+static gdouble elapsed_decode_time = 0;
+static gdouble elapsed_copying_time = 0;
+static int decoded_frame_cnt = 0;
+static int last_frame_cnt = 0;
+static QemuMutex profile_mutex;
+static int profile_init = 0;
+
+static gboolean
+maru_profile_cb (gpointer user_data)
+{
+    int decoding_fps = 0;
+    gdouble decoding_time = 0;
+    gdouble copying_time = 0;
+    gdouble total_latency_time = 0;
+
+    qemu_mutex_lock(&profile_mutex);
+    if (decoded_frame_cnt < 0) {
+        decoded_frame_cnt = 0;
+        last_frame_cnt = 0;
+        elapsed_decode_time = 0;
+        elapsed_copying_time = 0;
+        qemu_mutex_unlock(&profile_mutex);
+        return FALSE;
+    }
+
+    decoding_fps = decoded_frame_cnt - last_frame_cnt;
+    last_frame_cnt = decoded_frame_cnt;
+
+    decoding_time = elapsed_decode_time;
+    copying_time = elapsed_copying_time;
+    elapsed_decode_time = 0;
+    elapsed_copying_time = 0;
+    qemu_mutex_unlock(&profile_mutex);
+
+    total_latency_time = decoding_time + copying_time;
+    INFO("decoding fps=%d, latency=%f(decode=%f + get_picture=%f)\n",
+        decoding_fps, total_latency_time/decoding_fps,
+        decoding_time/decoding_fps, copying_time/decoding_fps);
+
+    return TRUE;
+}
+
+static void init_codec_profile(void)
+{
+    if (!profile_init) {
+        profile_init = 1;
+        qemu_mutex_init(&profile_mutex);
+        profile_decode_timer = g_timer_new();
+        profile_copy_timer = g_timer_new();
+    }
+}
+
+static void reset_codec_profile(void)
+{
+    qemu_mutex_lock(&profile_mutex);
+    decoded_frame_cnt = -1;
+    qemu_mutex_unlock(&profile_mutex);
+}
+
+static void begin_video_decode_profile(void)
+{
+    g_timer_start(profile_decode_timer);
+}
+
+static void begin_video_copy_profile(void)
+{
+    g_timer_start(profile_copy_timer);
+}
+
+static void end_video_decode_profile(void)
+{
+    g_timer_stop(profile_decode_timer);
+
+    qemu_mutex_lock(&profile_mutex);
+    if (decoded_frame_cnt == 0) {
+        g_timeout_add_seconds(1, maru_profile_cb, NULL);
+    }
+
+    elapsed_decode_time += g_timer_elapsed(profile_decode_timer, NULL);
+    decoded_frame_cnt++;
+    qemu_mutex_unlock(&profile_mutex);
+}
+
+static void end_video_copy_profile(void)
+{
+    g_timer_stop(profile_copy_timer);
+
+    qemu_mutex_lock(&profile_mutex);
+    elapsed_copying_time += g_timer_elapsed(profile_copy_timer, NULL);
+    qemu_mutex_unlock(&profile_mutex);
+}
+
+#define INIT_CODEC_PROFILE(s)   \
+    if ((s)->profile) {         \
+        init_codec_profile();   \
+    }
+#define RESET_CODEC_PROFILE()   \
+    if (profile_init) {         \
+        reset_codec_profile();  \
+    }
+#define BEGIN_VIDEO_DECODE_PROFILE()    \
+    if (profile_init) {                 \
+        begin_video_decode_profile();   \
+    }
+#define END_VIDEO_DECODE_PROFILE()  \
+    if (profile_init) {             \
+        end_video_decode_profile(); \
+    }
+#define BEGIN_VIDEO_COPY_PROFILE()  \
+    if (profile_init) {             \
+        begin_video_copy_profile(); \
+    }
+#define END_VIDEO_COPY_PROFILE()    \
+    if (profile_init) {             \
+        end_video_copy_profile();   \
+    }
+
+
 //
 // COMMON
 //
@@ -734,12 +857,18 @@ static void copy_video_decode_data(void *dst, void *opaque, size_t dummy)
     }
 
     if (dc->frame) {
+        // begin video copy profile
+        BEGIN_VIDEO_COPY_PROFILE();
+
         // if picture is exist...
         if (context->is_hwaccel) {
             plugin->get_picture(dst + dc->picture_buffer_offset, dc->frame);
         } else {
             default_get_picture(dst + dc->picture_buffer_offset, dc->frame, dc->avctx->pix_fmt);
         }
+
+        // end video copy profile
+        END_VIDEO_COPY_PROFILE();
     }
 
     g_free(dc);
@@ -816,9 +945,15 @@ static uint32_t parse_and_decode_video(AVCodecContext *avctx, AVFrame *picture,
             TRACE("not using parser %s\n", avctx->codec->name);
         }
 
+        // begin video decode profile
+        BEGIN_VIDEO_DECODE_PROFILE();
+
         len = avcodec_decode_video2(avctx, picture, (int *)got_picture, packet);
         TRACE("decode_video. len %d, got_picture %d\n", len, *got_picture);
 
+        // end video decode profile
+        END_VIDEO_DECODE_PROFILE();
+
         if (!pctx) {
             if (len == 0 && (*got_picture) == 0) {
                 ERR("decoding video didn't return any data! ctx_id %d len %d\n", ctx_id, len);
@@ -1690,6 +1825,9 @@ static bool init(MaruBrillCodecState *s, int ctx_id, void *data_buf)
 
     elem = (DeviceMemEntry *)data_buf;
 
+    // initialize profile resource
+    INIT_CODEC_PROFILE(s);
+
     // allocate AVCodecContext
     avctx = maru_brill_codec_alloc_context(s, ctx_id);
     if (!avctx) {
@@ -1819,6 +1957,9 @@ static bool deinit(MaruBrillCodecState *s, int ctx_id, void *data_buf)
 
     brillcodec_push_writequeue(s, NULL, 0, ctx_id, NULL);
 
+    // reset profile resource
+    RESET_CODEC_PROFILE();
+
     TRACE("leave: %s\n", __func__);
 
     return true;
index 53b36819277aebb8b95ca8d32e1a1ee2819babab..63d2cef1de115fdca7a430c5f029c2f9d0d2e9cf 100644 (file)
@@ -100,6 +100,8 @@ struct MaruBrillCodecState {
     CodecParam          ioparam;
 
     uint16_t             memory_monopolizing;
+
+    uint8_t             profile;
     CodecPlugin         *hwaccel_plugin;
 };
 
index ff028c570a307605cd446051de1c458dca63ee1e..15e02877d66b0adf868b6932abbdba0b27ca92ea 100644 (file)
@@ -62,6 +62,7 @@ enum device_cmd {
     DEVICE_CMD_GET_ELEMENT,
     DEVICE_CMD_GET_CONTEXT_INDEX,
     DEVICE_CMD_GET_DEVICE_INFO,
+    DEVICE_CMD_GET_PROFILE_STATUS,
 };
 
 enum thread_state {
@@ -189,6 +190,11 @@ static uint64_t brillcodec_read(void *opaque,
         TRACE("get context index: %d\n", ret);
         break;
 
+    case DEVICE_CMD_GET_PROFILE_STATUS:
+        ret = s->profile;
+        TRACE("profile status: %d\n", s->profile);
+        break;
+
     default:
         ERR("no avaiable command for read. %d\n", addr);
     }
@@ -294,6 +300,10 @@ static int brillcodec_initfn(PCIDevice *dev)
 # endif
 #endif
 
+    if (s->profile) {
+        INFO("Profile the brillcodec.(%d)\n", s->profile);
+    }
+
     return 0;
 }
 
@@ -323,6 +333,11 @@ static void brillcodec_reset(DeviceState *d)
     memset(&s->ioparam, 0, sizeof(CodecParam));
 }
 
+static Property brillcodec_props[] = {
+    DEFINE_PROP_UINT8("profile", MaruBrillCodecState, profile, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 static void brillcodec_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -334,6 +349,7 @@ static void brillcodec_class_init(ObjectClass *klass, void *data)
     k->device_id = PCI_DEVICE_ID_VIRTUAL_BRILL_CODEC;
     k->class_id = PCI_CLASS_OTHERS;
     dc->reset = brillcodec_reset;
+    dc->props = brillcodec_props;
     dc->desc = "Virtual new codec device for Tizen emulator";
 }