diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index c2f2675..e73f73e 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -71,6 +71,7 @@ struct osmo_gapk_pq { /* Processing queue management */ struct osmo_gapk_pq *osmo_gapk_pq_create(const char *name); +int osmo_gapk_pq_check(struct osmo_gapk_pq *pq, int strict); int osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq); int osmo_gapk_pq_execute(struct osmo_gapk_pq *pq); void osmo_gapk_pq_destroy(struct osmo_gapk_pq *pq); diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c index 6543eef..2aac0aa 100644 --- a/src/app_osmo_gapk.c +++ b/src/app_osmo_gapk.c @@ -521,6 +521,7 @@ make_processing_chain(struct gapk_state *gs) const struct osmo_gapk_codec_desc *codec_in, *codec_out; int need_dec, need_enc; + int rc; LOGP(DAPP, LOGL_NOTICE, "Creating a processing queue\n"); @@ -627,6 +628,11 @@ make_processing_chain(struct gapk_state *gs) return -1; } + /* Check the processing queue in strict mode */ + rc = osmo_gapk_pq_check(gs->pq, 1); + if (rc) + return rc; + return 0; } diff --git a/src/libosmogapk.map b/src/libosmogapk.map index 5fd7a7a..4494cdb 100644 --- a/src/libosmogapk.map +++ b/src/libosmogapk.map @@ -14,6 +14,7 @@ osmo_gapk_pq_execute; osmo_gapk_pq_destroy; osmo_gapk_pq_describe; +osmo_gapk_pq_check; osmo_gapk_pq_add_item; osmo_gapk_pq_queue_file_input; diff --git a/src/procqueue.c b/src/procqueue.c index 4de7a6a..b95b3ec 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -103,24 +103,65 @@ osmo_gapk_pq_add_item(struct osmo_gapk_pq *pq) return item; } -/*! prepare a processing queue; allocates buffers; checks lengths +/*! check a processing queue; make sure I/O data lengths are equal + * \param[in] pq Make sure both source and sink are preset + * \param[in] strict Processing Queue to be checked + * \returns 0 on succcess; negative on error */ +int +osmo_gapk_pq_check(struct osmo_gapk_pq *pq, int strict) +{ + struct osmo_gapk_pq_item *item_prev = NULL; + struct osmo_gapk_pq_item *item; + + /* Make sure I/O data lengths are equal */ + llist_for_each_entry(item, &pq->items, list) { + if (item_prev && item->len_in) { + if (item->len_in != item_prev->len_out) { + LOGPGAPK(LOGL_ERROR, "PQ '%s': item '%s/%s' requires " + "input size %u, but previous '%s/%s' has %u\n", + pq->name, item->cat_name, item->sub_name, + item->len_in, item_prev->cat_name, + item_prev->sub_name, item_prev->len_out); + return -EINVAL; + } + } + + /* Save pointer to the previous item */ + item_prev = item; + } + + if (strict) { + /* Make sure the first item is a source */ + item = llist_first_entry(&pq->items, + struct osmo_gapk_pq_item, list); + if (item->type != OSMO_GAPK_ITEM_TYPE_SOURCE) + goto src_sink_err; + + /* Make sure the last item is a sink */ + item = llist_last_entry(&pq->items, + struct osmo_gapk_pq_item, list); + if (item->type != OSMO_GAPK_ITEM_TYPE_SINK) + goto src_sink_err; + } + + return 0; + +src_sink_err: + LOGPGAPK(LOGL_ERROR, "PQ '%s': the first item should be a source, " + "and the last one should be a sink\n", pq->name); + return -EINVAL; +} + +/*! prepare a processing queue; allocates buffers * \param[in] pq Processing Queue to be prepared * \returns 0 on succcess; negative on error */ int osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq) { struct osmo_gapk_pq_item *item; - unsigned int len_prev = 0; /* Iterate over all items in queue */ llist_for_each_entry(item, &pq->items, list) { - /* Make sure I/O data lengths are equal */ - if (item->len_in && item->len_in != len_prev) { - LOGPGAPK(LOGL_ERROR, "PQ item requires input size %u, " - "but previous output is %u\n", item->len_in, len_prev); - return -EINVAL; - } - /* The sink item doesn't require an output buffer */ if (item->list.next != &pq->items) { unsigned int buf_size = item->len_out; @@ -136,14 +177,7 @@ osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq) item->buf = talloc_size(item, buf_size); if (!item->buf) return -ENOMEM; - } else { - /* Make sure the last item is a sink */ - if (item->len_out) - return -EINVAL; } - - /* Store output length for further comparation */ - len_prev = item->len_out; } return 0;