diff --git a/driver/vidc/inc/msm_vidc_driver.h b/driver/vidc/inc/msm_vidc_driver.h index 83c2bcdc1b..c32bdf8781 100644 --- a/driver/vidc/inc/msm_vidc_driver.h +++ b/driver/vidc/inc/msm_vidc_driver.h @@ -599,9 +599,9 @@ int signal_session_msg_receipt(struct msm_vidc_inst *inst, int msm_vidc_get_properties(struct msm_vidc_inst *inst); int msm_vidc_update_input_rate(struct msm_vidc_inst *inst, u64 time_us); int msm_vidc_add_buffer_stats(struct msm_vidc_inst *inst, - struct msm_vidc_buffer *buf); + struct msm_vidc_buffer *buf, u64 timestamp); int msm_vidc_remove_buffer_stats(struct msm_vidc_inst *inst, - struct msm_vidc_buffer *buf); + struct msm_vidc_buffer *buf, u64 timestamp); int msm_vidc_flush_buffer_stats(struct msm_vidc_inst *inst); int msm_vidc_get_input_rate(struct msm_vidc_inst *inst); int msm_vidc_get_frame_rate(struct msm_vidc_inst *inst); diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index 2c8182161d..9cf95f7cf9 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -917,12 +917,14 @@ struct msm_vidc_buffer_stats { u32 fbd_time_ms; u32 data_size; u32 flags; + u32 ts_offset; }; enum msm_vidc_buffer_stats_flag { - MSM_VIDC_STATS_FLAG_CORRUPT = BIT(0), - MSM_VIDC_STATS_FLAG_OVERFLOW = BIT(1), - MSM_VIDC_STATS_FLAG_NO_OUTPUT = BIT(2), + MSM_VIDC_STATS_FLAG_CORRUPT = BIT(0), + MSM_VIDC_STATS_FLAG_OVERFLOW = BIT(1), + MSM_VIDC_STATS_FLAG_NO_OUTPUT = BIT(2), + MSM_VIDC_STATS_FLAG_SUBFRAME_INPUT = BIT(3), }; struct msm_vidc_sort { diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index b6beae1710..7b39b619d9 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -318,6 +318,9 @@ static u32 msm_vidc_get_buffer_stats_flag(struct msm_vidc_inst *inst) if (inst->hfi_frame_info.no_output) flags |= MSM_VIDC_STATS_FLAG_NO_OUTPUT; + if (inst->hfi_frame_info.subframe_input) + flags |= MSM_VIDC_STATS_FLAG_SUBFRAME_INPUT; + return flags; } @@ -359,7 +362,7 @@ static int msm_vidc_try_suspend(struct msm_vidc_inst *inst) } int msm_vidc_add_buffer_stats(struct msm_vidc_inst *inst, - struct msm_vidc_buffer *buf) + struct msm_vidc_buffer *buf, u64 timestamp) { struct msm_vidc_buffer_stats *stats = NULL; struct msm_vidc_core *core; @@ -370,6 +373,9 @@ int msm_vidc_add_buffer_stats(struct msm_vidc_inst *inst, } core = inst->core; + if (!(msm_vidc_debug & VIDC_STAT)) + return 0; + /* stats applicable only to input & output buffers */ if (buf->type != MSM_VIDC_BUF_INPUT && buf->type != MSM_VIDC_BUF_OUTPUT) return -EINVAL; @@ -388,7 +394,8 @@ int msm_vidc_add_buffer_stats(struct msm_vidc_inst *inst, list_add_tail(&stats->list, &inst->buffer_stats_list); stats->frame_num = inst->debug_count.etb; - stats->timestamp = buf->timestamp; + stats->timestamp = timestamp; + stats->ts_offset = 0; stats->etb_time_ms = buf->start_time_ms; if (is_decode_session(inst)) stats->data_size = buf->data_size; @@ -397,10 +404,12 @@ int msm_vidc_add_buffer_stats(struct msm_vidc_inst *inst, } int msm_vidc_remove_buffer_stats(struct msm_vidc_inst *inst, - struct msm_vidc_buffer *buf) + struct msm_vidc_buffer *buf, u64 timestamp) { struct msm_vidc_buffer_stats *stats = NULL, *dummy_stats = NULL; + struct msm_vidc_buffer_stats *prev_stats = NULL; struct msm_vidc_core *core; + bool remove_stat = false, is_first_stat = false;; if (!inst || !inst->core || !buf) { d_vpr_e("%s: invalid params\n", __func__); @@ -408,6 +417,9 @@ int msm_vidc_remove_buffer_stats(struct msm_vidc_inst *inst, } core = inst->core; + if (!(msm_vidc_debug & VIDC_STAT)) + return 0; + /* stats applicable only to input & output buffers */ if (buf->type != MSM_VIDC_BUF_INPUT && buf->type != MSM_VIDC_BUF_OUTPUT) return -EINVAL; @@ -416,38 +428,51 @@ int msm_vidc_remove_buffer_stats(struct msm_vidc_inst *inst, buf->end_time_ms = (ktime_get_ns() / 1000 - inst->initial_time_us) / 1000; list_for_each_entry_safe(stats, dummy_stats, &inst->buffer_stats_list, list) { - if (stats->timestamp == buf->timestamp) { - if (buf->type == MSM_VIDC_BUF_INPUT) { - /* skip - already updated(multiple input - single output case) */ - if (stats->ebd_time_ms) - continue; + if (stats->timestamp - stats->ts_offset != timestamp) + continue; - /* ebd: update end ts and return */ - stats->ebd_time_ms = buf->end_time_ms; - stats->flags |= msm_vidc_get_buffer_stats_flag(inst); + remove_stat = false; + if (buf->type == MSM_VIDC_BUF_INPUT) { + /* skip - ebd already updated(multiple input - single output case) */ + if (stats->ebd_time_ms) + continue; - /* remove entry - no output attached */ - if (stats->flags & MSM_VIDC_STATS_FLAG_NO_OUTPUT) { - list_del_init(&stats->list); - msm_vidc_pool_free(inst, stats); - } - } else if (buf->type == MSM_VIDC_BUF_OUTPUT) { - /* skip - ebd not arrived(single input - multiple output case) */ - if (!stats->ebd_time_ms) - continue; + /* ebd: update end ts and return */ + stats->ebd_time_ms = buf->end_time_ms; + stats->flags |= msm_vidc_get_buffer_stats_flag(inst); - /* fbd: update end ts and remove entry */ - list_del_init(&stats->list); - stats->ftb_time_ms = buf->start_time_ms; - stats->fbd_time_ms = buf->end_time_ms; - stats->flags |= msm_vidc_get_buffer_stats_flag(inst); - if (is_encode_session(inst)) - stats->data_size = buf->data_size; + /* multi in - single out (interlace/slice decoding case) */ + is_first_stat = list_is_first(&stats->list, &inst->buffer_stats_list); + if (!is_first_stat) { + prev_stats = list_prev_entry(stats, list); - print_buffer_stats(VIDC_STAT, "stat", inst, stats); - - msm_vidc_pool_free(inst, stats); + /* add offset if FW requires more etb's to process output */ + if (prev_stats->flags & MSM_VIDC_STATS_FLAG_SUBFRAME_INPUT) + stats->ts_offset = stats->timestamp - prev_stats->timestamp; } + + /* remove entry - no output attached */ + remove_stat = !!(stats->flags & MSM_VIDC_STATS_FLAG_NO_OUTPUT); + remove_stat |= stats->ebd_time_ms && stats->fbd_time_ms; + } else if (buf->type == MSM_VIDC_BUF_OUTPUT) { + /* skip - ebd already updated(encoder superframe case) */ + if (stats->fbd_time_ms) + continue; + + /* fbd: update end ts */ + stats->ftb_time_ms = buf->start_time_ms; + stats->fbd_time_ms = buf->end_time_ms; + stats->flags |= msm_vidc_get_buffer_stats_flag(inst); + if (is_encode_session(inst)) + stats->data_size = buf->data_size; + + remove_stat |= stats->ebd_time_ms && stats->fbd_time_ms; + } + /* remove stats node */ + if (remove_stat) { + list_del_init(&stats->list); + print_buffer_stats(VIDC_STAT, "stat", inst, stats); + msm_vidc_pool_free(inst, stats); } } @@ -2832,9 +2857,6 @@ struct msm_vidc_buffer *msm_vidc_get_driver_buf(struct msm_vidc_inst *inst, } } - /* update start timestamp */ - msm_vidc_add_buffer_stats(inst, buf); - return buf; } diff --git a/driver/vidc/src/venus_hfi.c b/driver/vidc/src/venus_hfi.c index c151eadefb..046aa75515 100644 --- a/driver/vidc/src/venus_hfi.c +++ b/driver/vidc/src/venus_hfi.c @@ -1825,6 +1825,9 @@ int venus_hfi_queue_super_buffer(struct msm_vidc_inst *inst, if (rc) goto unlock; + /* update start timestamp */ + msm_vidc_add_buffer_stats(inst, buffer, hfi_buffer.timestamp); + cnt++; } unlock: @@ -1884,7 +1887,7 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst, { int rc = 0; struct msm_vidc_core *core; - struct hfi_buffer hfi_buffer; + struct hfi_buffer hfi_buffer, hfi_meta_buffer; if (!inst || !inst->core || !inst->packet || !inst->capabilities) { d_vpr_e("%s: invalid params\n", __func__); @@ -1920,7 +1923,7 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst, goto unlock; if (metabuf) { - rc = get_hfi_buffer(inst, metabuf, &hfi_buffer); + rc = get_hfi_buffer(inst, metabuf, &hfi_meta_buffer); if (rc) goto unlock; rc = hfi_create_packet(inst->packet, @@ -1930,8 +1933,8 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst, HFI_PAYLOAD_STRUCTURE, get_hfi_port_from_buffer_type(inst, metabuf->type), core->packet_id++, - &hfi_buffer, - sizeof(hfi_buffer)); + &hfi_meta_buffer, + sizeof(hfi_meta_buffer)); if (rc) goto unlock; } @@ -1964,6 +1967,9 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst, if (rc) goto unlock; + /* update start timestamp */ + msm_vidc_add_buffer_stats(inst, buffer, hfi_buffer.timestamp); + unlock: core_unlock(core, __func__); return rc; diff --git a/driver/vidc/src/venus_hfi_response.c b/driver/vidc/src/venus_hfi_response.c index 6c1b9e2a07..1418ef2f87 100644 --- a/driver/vidc/src/venus_hfi_response.c +++ b/driver/vidc/src/venus_hfi_response.c @@ -822,6 +822,8 @@ static int handle_input_buffer(struct msm_vidc_inst *inst, if (buffer->addr_offset / frame_size < batch_size - 1) { i_vpr_l(inst, "%s: superframe last buffer not reached: %u, %u, %u\n", __func__, buffer->addr_offset, frame_size, batch_size); + /* remove buffer stats for all the subframes in a superframe */ + msm_vidc_remove_buffer_stats(inst, buf, buffer->timestamp); return 0; } } @@ -848,8 +850,8 @@ static int handle_input_buffer(struct msm_vidc_inst *inst, print_vidc_buffer(VIDC_HIGH, "high", "dqbuf", inst, buf); msm_vidc_update_stats(inst, buf, MSM_VIDC_DEBUGFS_EVENT_EBD); - /* etd: update end timestamp and flags in stats entry */ - msm_vidc_remove_buffer_stats(inst, buf); + /* ebd: update end timestamp and flags in stats entry */ + msm_vidc_remove_buffer_stats(inst, buf, buffer->timestamp); return rc; } @@ -1026,7 +1028,7 @@ static int handle_output_buffer(struct msm_vidc_inst *inst, msm_vidc_update_stats(inst, buf, MSM_VIDC_DEBUGFS_EVENT_FBD); /* fbd: print stats and remove entry */ - msm_vidc_remove_buffer_stats(inst, buf); + msm_vidc_remove_buffer_stats(inst, buf, buffer->timestamp); return rc; }