From 69c69d01a4b7461ba5895395c8461d64f6d9a763 Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Fri, 18 Mar 2022 19:45:26 +0200 Subject: [PATCH] Tools: Testbench: Add capture direction and multi-pipeline run This patch changes testbench to retrieve pipeline direction from pipeline host direction. Earlier all pipelines were forced to playback. The topology parsing filters the parsed pipelines to command line specified pipeline IDs. All the pipeline operations are done looped to these pipelines to be able to simulate multiple simultaneous pipelines. The pipeline context struct remains single. So the simulation works only for pipelines with identical PCM format and rate. Signed-off-by: Seppo Ingalsuo --- src/include/ipc/topology.h | 1 + src/include/sof/audio/ipc-config.h | 1 + src/ipc/ipc3/helper.c | 1 + tools/testbench/common_test.c | 80 +++---- tools/testbench/file.c | 1 + .../testbench/include/testbench/common_test.h | 14 +- tools/testbench/testbench.c | 221 +++++++++++++----- tools/testbench/topology.c | 23 +- 8 files changed, 221 insertions(+), 121 deletions(-) diff --git a/src/include/ipc/topology.h b/src/include/ipc/topology.h index c304824f9..5d072729d 100644 --- a/src/include/ipc/topology.h +++ b/src/include/ipc/topology.h @@ -245,6 +245,7 @@ struct sof_ipc_comp_file { char *fn; uint32_t mode; uint32_t frame_fmt; + uint32_t direction; /**< SOF_IPC_STREAM_ */ } __attribute__((packed, aligned(4))); /* frees components, buffers and pipelines diff --git a/src/include/sof/audio/ipc-config.h b/src/include/sof/audio/ipc-config.h index 9924734c4..07636e7b1 100644 --- a/src/include/sof/audio/ipc-config.h +++ b/src/include/sof/audio/ipc-config.h @@ -98,6 +98,7 @@ struct ipc_comp_file { char *fn; uint32_t mode; uint32_t frame_fmt; + uint32_t direction; /**< SOF_IPC_STREAM_ */ } __attribute__((packed, aligned(4))); #endif diff --git a/src/ipc/ipc3/helper.c b/src/ipc/ipc3/helper.c index 3a3e44de8..af0b621ae 100644 --- a/src/ipc/ipc3/helper.c +++ b/src/ipc/ipc3/helper.c @@ -217,6 +217,7 @@ static void comp_specific_builder(struct sof_ipc_comp *comp, config->file.frame_fmt = file->frame_fmt; config->file.mode = file->mode; config->file.rate = file->rate; + config->file.direction = file->direction; break; #else case SOF_COMP_HOST: diff --git a/tools/testbench/common_test.c b/tools/testbench/common_test.c index 3bf0cda91..78808c845 100644 --- a/tools/testbench/common_test.c +++ b/tools/testbench/common_test.c @@ -97,32 +97,26 @@ void tb_free(struct sof *sof) free(sof->ipc); } -/* set up pcm params, prepare and trigger pipeline */ -int tb_pipeline_start(struct ipc *ipc, struct pipeline *p, - struct tplg_context *ctx) +/* Get pipeline host component */ +static struct comp_dev *tb_get_pipeline_host(struct pipeline *p) +{ + struct comp_dev *cd; + + cd = p->source_comp; + if (cd->direction == SOF_IPC_STREAM_CAPTURE) + cd = p->sink_comp; + + return cd; +} + +/* set up pcm params, prepare and trigger pipeline */ +int tb_pipeline_start(struct ipc *ipc, struct pipeline *p) { - struct ipc_comp_dev *pcm_dev; struct comp_dev *cd; int ret; - /* set up pipeline params */ - ret = tb_pipeline_params(ipc, p, ctx); - if (ret < 0) { - fprintf(stderr, "error: pipeline params failed: %s\n", - strerror(ret)); - return ret; - } - - /* Get IPC component device for pipeline */ - pcm_dev = ipc_get_comp_by_id(ipc, p->sched_id); - if (!pcm_dev) { - fprintf(stderr, "error: ipc get comp failed: %s\n", - strerror(ret)); - return ret; - } - - /* Point to pipeline component device */ - cd = pcm_dev->cd; + /* Get pipeline host component */ + cd = tb_get_pipeline_host(p); /* Component prepare */ ret = pipeline_prepare(p, cd); @@ -133,7 +127,7 @@ int tb_pipeline_start(struct ipc *ipc, struct pipeline *p, } /* Start the pipeline */ - ret = pipeline_trigger(p, cd, COMP_TRIGGER_PRE_START); + ret = pipeline_trigger(cd->pipeline, cd, COMP_TRIGGER_PRE_START); if (ret < 0) { fprintf(stderr, "error: Failed to start pipeline command: %s\n", strerror(ret)); @@ -144,24 +138,15 @@ int tb_pipeline_start(struct ipc *ipc, struct pipeline *p, } /* set up pcm params, prepare and trigger pipeline */ -int tb_pipeline_stop(struct ipc *ipc, struct pipeline *p, - struct tplg_context *ctx) +int tb_pipeline_stop(struct ipc *ipc, struct pipeline *p) { - struct ipc_comp_dev *pcm_dev; struct comp_dev *cd; int ret; - /* Get IPC component device for pipeline */ - pcm_dev = ipc_get_comp_by_id(ipc, p->sched_id); - if (!pcm_dev) { - fprintf(stderr, "error: ipc get comp failed\n"); - return -EINVAL; - } + /* Get pipeline host component */ + cd = tb_get_pipeline_host(p); - /* Point to pipeline component device */ - cd = pcm_dev->cd; - - ret = pipeline_trigger(p, cd, COMP_TRIGGER_STOP); + ret = pipeline_trigger(cd->pipeline, cd, COMP_TRIGGER_STOP); if (ret < 0) { fprintf(stderr, "error: Failed to stop pipeline command: %s\n", strerror(ret)); @@ -171,22 +156,13 @@ int tb_pipeline_stop(struct ipc *ipc, struct pipeline *p, } /* set up pcm params, prepare and trigger pipeline */ -int tb_pipeline_reset(struct ipc *ipc, struct pipeline *p, - struct tplg_context *ctx) +int tb_pipeline_reset(struct ipc *ipc, struct pipeline *p) { - struct ipc_comp_dev *pcm_dev; struct comp_dev *cd; int ret; - /* Get IPC component device for pipeline */ - pcm_dev = ipc_get_comp_by_id(ipc, p->sched_id); - if (!pcm_dev) { - fprintf(stderr, "error: ipc get comp failed\n"); - return -EINVAL; - } - - /* Point to pipeline component device */ - cd = pcm_dev->cd; + /* Get pipeline host component */ + cd = tb_get_pipeline_host(p); ret = pipeline_reset(p, cd); if (ret < 0) @@ -223,7 +199,6 @@ int tb_pipeline_params(struct ipc *ipc, struct pipeline *p, params.comp_id = p->comp_id; params.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; params.params.frame_fmt = ctx->frame_fmt; - params.params.direction = SOF_IPC_STREAM_PLAYBACK; params.params.rate = ctx->fs_in; params.params.channels = ctx->channels_in; @@ -255,8 +230,11 @@ int tb_pipeline_params(struct ipc *ipc, struct pipeline *p, return -EINVAL; } - /* point to pipeline component device */ - cd = pcm_dev->cd; + /* Get pipeline host component */ + cd = tb_get_pipeline_host(p); + + /* Set pipeline params direction from scheduling component */ + params.params.direction = cd->direction; /* pipeline params */ ret = pipeline_params(p, cd, ¶ms); diff --git a/tools/testbench/file.c b/tools/testbench/file.c index bbe222087..5808c7d4f 100644 --- a/tools/testbench/file.c +++ b/tools/testbench/file.c @@ -587,6 +587,7 @@ static struct comp_dev *file_new(const struct comp_driver *drv, cd->rate = ipc_file->rate; cd->channels = ipc_file->channels; cd->frame_fmt = ipc_file->frame_fmt; + dev->direction = ipc_file->direction; /* open file handle(s) depending on mode */ switch (cd->fs.mode) { diff --git a/tools/testbench/include/testbench/common_test.h b/tools/testbench/include/testbench/common_test.h index 2a0c3e4f3..0241df4f5 100644 --- a/tools/testbench/include/testbench/common_test.h +++ b/tools/testbench/include/testbench/common_test.h @@ -21,6 +21,7 @@ #define DEBUG_MSG_LEN 1024 #define MAX_LIB_NAME_LEN 1024 +#define MAX_INPUT_FILE_NUM 16 #define MAX_OUTPUT_FILE_NUM 16 /* number of widgets types supported in testbench */ @@ -36,8 +37,9 @@ struct tplg_context; */ struct testbench_prm { char *tplg_file; /* topology file to use */ - char *input_file; /* input file name */ + char *input_file[MAX_INPUT_FILE_NUM]; /* input file names */ char *output_file[MAX_OUTPUT_FILE_NUM]; /* output file names */ + int input_file_num; /* number of input files */ int output_file_num; /* number of output files */ char *bits_in; /* input bit format */ int pipelines[MAX_OUTPUT_FILE_NUM]; /* output file names */ @@ -58,6 +60,7 @@ struct testbench_prm { FILE *file; char *pipeline_string; int output_file_index; + int input_file_index; /* global cmd line args that can override topology */ enum sof_ipc_frame cmd_frame_fmt; @@ -89,17 +92,14 @@ void sys_comp_filewrite_init(void); int tb_setup(struct sof *sof, struct testbench_prm *tp); void tb_free(struct sof *sof); -int tb_pipeline_start(struct ipc *ipc, struct pipeline *p, - struct tplg_context *ctx); +int tb_pipeline_start(struct ipc *ipc, struct pipeline *p); int tb_pipeline_params(struct ipc *ipc, struct pipeline *p, struct tplg_context *ctx); -int tb_pipeline_stop(struct ipc *ipc, struct pipeline *p, - struct tplg_context *ctx); +int tb_pipeline_stop(struct ipc *ipc, struct pipeline *p); -int tb_pipeline_reset(struct ipc *ipc, struct pipeline *p, - struct tplg_context *ctx); +int tb_pipeline_reset(struct ipc *ipc, struct pipeline *p); void debug_print(char *message); diff --git a/tools/testbench/testbench.c b/tools/testbench/testbench.c index a5c5455e0..24abbce26 100644 --- a/tools/testbench/testbench.c +++ b/tools/testbench/testbench.c @@ -117,6 +117,36 @@ static int parse_output_files(char *outputs, struct testbench_prm *tp) return 0; } +/* + * Parse inputfilenames from user input + */ +static int parse_input_files(char *inputs, struct testbench_prm *tp) +{ + char *input_token = NULL; + char *token = strtok_r(inputs, ",", &input_token); + int index; + + for (index = 0; index < MAX_INPUT_FILE_NUM && token; index++) { + /* get input file name with current index */ + tp->input_file[index] = strdup(token); + + /* next input */ + token = strtok_r(NULL, ",", &input_token); + } + + if (index == MAX_INPUT_FILE_NUM && token) { + fprintf(stderr, "error: max input file number is %d\n", + MAX_INPUT_FILE_NUM); + for (index = 0; index < MAX_INPUT_FILE_NUM; index++) + free(tp->input_file[index]); + return -EINVAL; + } + + /* set total input file number */ + tp->input_file_num = index; + return 0; +} + static int parse_pipelines(char *pipelines, struct testbench_prm *tp) { char *output_token = NULL; @@ -355,7 +385,7 @@ static int parse_input_args(int argc, char **argv, struct testbench_prm *tp) switch (option) { /* input sample file */ case 'i': - tp->input_file = strdup(optarg); + ret = parse_input_files(optarg, tp); break; /* output sample files */ @@ -456,81 +486,143 @@ static int parse_input_args(int argc, char **argv, struct testbench_prm *tp) return ret; } -static int test_pipeline_stop(struct pipeline_thread_data *ptdata, - struct tplg_context *ctx) +static struct pipeline *get_pipeline_by_id(int id) { struct ipc_comp_dev *pcm_dev; - struct pipeline *p; + struct ipc *ipc = sof_get()->ipc; - pcm_dev = ipc_get_comp_by_id(sof_get()->ipc, ctx->sched_id); - p = pcm_dev->cd->pipeline; - - return tb_pipeline_stop(sof_get()->ipc, p, ctx); + pcm_dev = ipc_get_ppl_src_comp(ipc, id); + return pcm_dev->cd->pipeline; } -static int test_pipeline_reset(struct pipeline_thread_data *ptdata, - struct tplg_context *ctx) +static int test_pipeline_stop(struct pipeline_thread_data *ptdata) { - struct ipc_comp_dev *pcm_dev; + struct testbench_prm *tp = ptdata->tp; struct pipeline *p; + struct ipc *ipc = sof_get()->ipc; + int ret = 0; + int i; - pcm_dev = ipc_get_comp_by_id(sof_get()->ipc, ctx->sched_id); - p = pcm_dev->cd->pipeline; + for (i = 0; i < tp->pipeline_num; i++) { + p = get_pipeline_by_id(tp->pipelines[i]); + ret = tb_pipeline_stop(ipc, p); + if (ret < 0) + break; + } - return tb_pipeline_reset(sof_get()->ipc, p, ctx); + return ret; } -static int test_pipeline_start(struct pipeline_thread_data *ptdata, - struct tplg_context *ctx) +static int test_pipeline_reset(struct pipeline_thread_data *ptdata) +{ + struct testbench_prm *tp = ptdata->tp; + struct pipeline *p; + struct ipc *ipc = sof_get()->ipc; + int ret = 0; + int i; + + for (i = 0; i < tp->pipeline_num; i++) { + p = get_pipeline_by_id(tp->pipelines[i]); + ret = tb_pipeline_reset(ipc, p); + if (ret < 0) + break; + } + + return ret; +} + +static void test_pipeline_free(struct pipeline_thread_data *ptdata) +{ + struct testbench_prm *tp = ptdata->tp; + int i; + + for (i = 0; i < tp->pipeline_num; i++) + test_pipeline_free_comps(tp->pipelines[i]); +} + +static int test_pipeline_params(struct pipeline_thread_data *ptdata, struct tplg_context *ctx) { struct testbench_prm *tp = ptdata->tp; struct ipc_comp_dev *pcm_dev; struct pipeline *p; + struct ipc *ipc = sof_get()->ipc; + int ret = 0; + int i; /* Run pipeline until EOF from fileread */ - pcm_dev = ipc_get_comp_by_id(sof_get()->ipc, ctx->sched_id); - if (!pcm_dev) { - fprintf(stderr, "error: pipeline has no scheduling component %d\n", - ctx->sched_id); - return -EINVAL; + + for (i = 0; i < tp->pipeline_num; i++) { + pcm_dev = ipc_get_ppl_src_comp(ipc, tp->pipelines[i]); + if (!pcm_dev) { + fprintf(stderr, "error: pipeline %d has no source component\n", + tp->pipelines[i]); + return -EINVAL; + } + + /* set up pipeline params */ + p = pcm_dev->cd->pipeline; + + /* input and output sample rate */ + if (!ctx->fs_in) + ctx->fs_in = p->period * p->frames_per_sched; + + if (!ctx->fs_out) + ctx->fs_out = p->period * p->frames_per_sched; + + ret = tb_pipeline_params(ipc, p, ctx); + if (ret < 0) { + fprintf(stderr, "error: pipeline params failed: %s\n", + strerror(ret)); + return ret; + } } - p = pcm_dev->cd->pipeline; - /* input and output sample rate */ - if (!ctx->fs_in) - ctx->fs_in = p->period * p->frames_per_sched; + return 0; +} - if (!ctx->fs_out) - ctx->fs_out = p->period * p->frames_per_sched; +static int test_pipeline_start(struct pipeline_thread_data *ptdata) +{ + struct testbench_prm *tp = ptdata->tp; + struct pipeline *p; + struct ipc *ipc = sof_get()->ipc; + int i; - /* do we need to apply copy count limit ? */ - if (tp->copy_check) - test_pipeline_set_test_limits(ctx->pipeline_id, tp->copy_iterations, 0); + /* Run pipeline until EOF from fileread */ + for (i = 0; i < tp->pipeline_num; i++) { + p = get_pipeline_by_id(tp->pipelines[i]); - /* set pipeline params and trigger start */ - if (tb_pipeline_start(sof_get()->ipc, p, ctx) < 0) { - fprintf(stderr, "error: pipeline params\n"); - return -EINVAL; + /* do we need to apply copy count limit ? */ + if (tp->copy_check) + test_pipeline_set_test_limits(tp->pipelines[i], tp->copy_iterations, 0); + + /* set pipeline params and trigger start */ + if (tb_pipeline_start(ipc, p) < 0) { + fprintf(stderr, "error: pipeline params\n"); + return -EINVAL; + } } return 0; } -static int test_pipeline_get_state(struct pipeline_thread_data *ptdata, - struct tplg_context *ctx) +static bool test_pipeline_check_state(struct pipeline_thread_data *ptdata, int state) { - struct ipc_comp_dev *pcm_dev; + struct testbench_prm *tp = ptdata->tp; struct pipeline *p; + int i; /* Run pipeline until EOF from fileread */ - pcm_dev = ipc_get_comp_by_id(sof_get()->ipc, ctx->sched_id); - p = pcm_dev->cd->pipeline; - return p->pipe_task->state; + for (i = 0; i < tp->pipeline_num; i++) { + p = get_pipeline_by_id(tp->pipelines[i]); + if (p->pipe_task->state == state) + return true; + } + + return false; } -static int test_pipeline_load(struct pipeline_thread_data *ptdata, - struct tplg_context *ctx, int pipeline_id) +static int test_pipeline_load(struct pipeline_thread_data *ptdata, struct tplg_context *ctx) { struct testbench_prm *tp = ptdata->tp; int ret; @@ -543,7 +635,6 @@ static int test_pipeline_load(struct pipeline_thread_data *ptdata, ctx->sof = sof_get(); ctx->tp = tp; ctx->tplg_file = tp->tplg_file; - ctx->pipeline_id = pipeline_id; ctx->fs_in = tp->cmd_fs_in; ctx->fs_out = tp->cmd_fs_out; ctx->channels_in = tp->cmd_channels_in; @@ -558,12 +649,6 @@ static int test_pipeline_load(struct pipeline_thread_data *ptdata, return ret; } -static void test_pipeline_free(struct pipeline_thread_data *ptdata, - struct tplg_context *ctx, int pipeline_id) -{ - test_pipeline_free_comps(pipeline_id); -} - static void test_pipeline_stats(struct pipeline_thread_data *ptdata, struct tplg_context *ctx, uint64_t delta) { @@ -622,6 +707,10 @@ static void test_pipeline_stats(struct pipeline_thread_data *ptdata, printf("Input bit format: %s\n", tp->bits_in); printf("Input sample rate: %d\n", ctx->fs_in); printf("Output sample rate: %d\n", ctx->fs_out); + for (i = 0; i < tp->input_file_num; i++) { + printf("Input[%d] read from file: \"%s\"\n", + i, tp->input_file[i]); + } for (i = 0; i < tp->output_file_num; i++) { printf("Output[%d] written to file: \"%s\"\n", i, tp->output_file[i]); @@ -659,14 +748,21 @@ static void *pipline_test(void *data) printf(" Test Start %d\n", dp_count); printf("==========================================================\n"); - err = test_pipeline_load(ptdata, &ctx, tp->pipelines[0]); + err = test_pipeline_load(ptdata, &ctx); if (err < 0) { fprintf(stderr, "error: pipeline load %d failed %d\n", dp_count, err); break; } - err = test_pipeline_start(ptdata, &ctx); + err = test_pipeline_params(ptdata, &ctx); + if (err < 0) { + fprintf(stderr, "error: pipeline params %d failed %d\n", + dp_count, err); + break; + } + + err = test_pipeline_start(ptdata); if (err < 0) { fprintf(stderr, "error: pipeline run %d failed %d\n", dp_count, err); @@ -691,8 +787,7 @@ static void *pipline_test(void *data) err = nanosleep(&ts, &ts); if (err == 0) { nsleep_time += tp->tick_period_us; /* sleep fully completed */ - if (test_pipeline_get_state(ptdata, &ctx) == - SOF_TASK_STATE_CANCEL) { + if (test_pipeline_check_state(ptdata, SOF_TASK_STATE_CANCEL)) { fprintf(stdout, "pipeline cancelled !\n"); break; } @@ -707,7 +802,7 @@ static void *pipline_test(void *data) } clock_gettime(CLOCK_MONOTONIC, &td1); - err = test_pipeline_stop(ptdata, &ctx); + err = test_pipeline_stop(ptdata); if (err < 0) { fprintf(stderr, "error: pipeline stop %d failed %d\n", dp_count, err); @@ -718,14 +813,14 @@ static void *pipline_test(void *data) delta += (td1.tv_nsec - td0.tv_nsec) / 1000; test_pipeline_stats(ptdata, &ctx, delta); - err = test_pipeline_reset(ptdata, &ctx); + err = test_pipeline_reset(ptdata); if (err < 0) { fprintf(stderr, "error: pipeline stop %d failed %d\n", dp_count, err); break; } - test_pipeline_free(ptdata, &ctx, tp->pipelines[0]); + test_pipeline_free(ptdata); ptdata->count++; dp_count++; @@ -746,12 +841,15 @@ int main(int argc, char **argv) tp.cmd_fs_in = 0; tp.cmd_fs_out = 0; tp.bits_in = 0; - tp.input_file = NULL; tp.tplg_file = NULL; + tp.input_file_num = 0; tp.output_file_num = 0; for (i = 0; i < MAX_OUTPUT_FILE_NUM; i++) tp.output_file[i] = NULL; + for (i = 0; i < MAX_INPUT_FILE_NUM; i++) + tp.input_file[i] = NULL; + tp.cmd_channels_in = TESTBENCH_NCH; tp.cmd_channels_out = 0; tp.max_pipeline_id = 0; @@ -781,8 +879,8 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } - if (!tp.input_file) { - fprintf(stderr, "input audio file not specified, use -i file\n"); + if (!tp.input_file_num) { + fprintf(stderr, "input files not specified, use -i file1,file2\n"); print_usage(argv[0]); exit(EXIT_FAILURE); } @@ -844,10 +942,13 @@ join: out: /* free all other data */ free(tp.bits_in); - free(tp.input_file); free(tp.tplg_file); for (i = 0; i < tp.output_file_num; i++) free(tp.output_file[i]); + + for (i = 0; i < tp.input_file_num; i++) + free(tp.input_file[i]); + free(tp.pipeline_string); #ifdef TESTBENCH_CACHE_CHECK diff --git a/tools/testbench/topology.c b/tools/testbench/topology.c index ba6d79085..f69d57728 100644 --- a/tools/testbench/topology.c +++ b/tools/testbench/topology.c @@ -245,16 +245,19 @@ static int load_fileread(struct tplg_context *ctx, int dir) } /* configure fileread */ - fileread.fn = strdup(tp->input_file); + fileread.fn = strdup(tp->input_file[tp->input_file_index]); + if (tp->input_file_index == 0) + tp->fr_id = ctx->comp_id; /* use fileread comp as scheduling comp */ - tp->fr_id = ctx->comp_id; ctx->sched_id = ctx->comp_id; + tp->input_file_index++; /* Set format from testbench command line*/ fileread.rate = ctx->fs_in; fileread.channels = ctx->channels_in; fileread.frame_fmt = ctx->frame_fmt; + fileread.direction = dir; /* Set type depending on direction */ fileread.comp.type = (dir == SOF_IPC_STREAM_PLAYBACK) ? @@ -304,6 +307,7 @@ static int load_filewrite(struct tplg_context *ctx, int dir) filewrite.rate = ctx->fs_out; filewrite.channels = ctx->channels_out; filewrite.frame_fmt = ctx->frame_fmt; + filewrite.direction = dir; /* Set type depending on direction */ filewrite.comp.type = (dir == SOF_IPC_STREAM_PLAYBACK) ? @@ -361,6 +365,7 @@ int parse_topology(struct tplg_context *ctx) int ret = 0; size_t file_size; size_t size; + bool pipeline_match; /* initialize output file index */ tp->output_file_index = 0; @@ -410,7 +415,17 @@ int parse_topology(struct tplg_context *ctx) ctx->hdr = hdr; - if (hdr->index != ctx->pipeline_id) { + pipeline_match = false; + for (i = 0; i < tp->pipeline_num; i++) { + if (hdr->index == tp->pipelines[i]) { + pipeline_match = true; + break; + } + } + + if (!pipeline_match) { + sprintf(message, "skipped pipeline %d\n", hdr->index); + debug_print(message); next = get_next_hdr(ctx, hdr, file_size); if (next < 0) goto out; @@ -418,6 +433,7 @@ int parse_topology(struct tplg_context *ctx) continue; else goto finish; + } /* parse header and load the next block based on type */ @@ -431,6 +447,7 @@ int parse_topology(struct tplg_context *ctx) debug_print(message); /* update max pipeline_id */ + ctx->pipeline_id = hdr->index; if (hdr->index > tp->max_pipeline_id) tp->max_pipeline_id = hdr->index;