Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  dsp_pipeline.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * dsp_pipeline.c: pipelined audio processing
 *
 * Copyright (C) 2007, Nadi Sarrar
 *
 * Nadi Sarrar <nadi@beronet.com>
 */


#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/string.h>
#include <linux/mISDNif.h>
#include <linux/mISDNdsp.h>
#include <linux/export.h>
#include "dsp.h"
#include "dsp_hwec.h"

struct dsp_pipeline_entry {
 struct mISDN_dsp_element *elem;
 void                *p;
 struct list_head     list;
};
struct dsp_element_entry {
 struct mISDN_dsp_element *elem;
 struct device      dev;
 struct list_head     list;
};

static LIST_HEAD(dsp_elements);

/* sysfs */
static const struct class elements_class = {
 .name = "dsp_pipeline",
};

static ssize_t
attr_show_args(struct device *dev, struct device_attribute *attr, char *buf)
{
 struct mISDN_dsp_element *elem = dev_get_drvdata(dev);
 int i;
 char *p = buf;

 *buf = 0;
 for (i = 0; i < elem->num_args; i++)
  p += sprintf(p, "Name: %s\n%s%s%sDescription: %s\n\n",
        elem->args[i].name,
        elem->args[i].def ? "Default: " : "",
        elem->args[i].def ? elem->args[i].def : "",
        elem->args[i].def ? "\n" : "",
        elem->args[i].desc);

 return p - buf;
}

static struct device_attribute element_attributes[] = {
 __ATTR(args, 0444, attr_show_args, NULL),
};

static void
mISDN_dsp_dev_release(struct device *dev)
{
 struct dsp_element_entry *entry =
  container_of(dev, struct dsp_element_entry, dev);
 list_del(&entry->list);
 kfree(entry);
}

int mISDN_dsp_element_register(struct mISDN_dsp_element *elem)
{
 struct dsp_element_entry *entry;
 int ret, i;

 if (!elem)
  return -EINVAL;

 entry = kzalloc(sizeof(struct dsp_element_entry), GFP_ATOMIC);
 if (!entry)
  return -ENOMEM;

 INIT_LIST_HEAD(&entry->list);
 entry->elem = elem;

 entry->dev.class = &elements_class;
 entry->dev.release = mISDN_dsp_dev_release;
 dev_set_drvdata(&entry->dev, elem);
 dev_set_name(&entry->dev, "%s", elem->name);
 ret = device_register(&entry->dev);
 if (ret) {
  printk(KERN_ERR "%s: failed to register %s\n",
         __func__, elem->name);
  goto err1;
 }
 list_add_tail(&entry->list, &dsp_elements);

 for (i = 0; i < ARRAY_SIZE(element_attributes); ++i) {
  ret = device_create_file(&entry->dev,
      &element_attributes[i]);
  if (ret) {
   printk(KERN_ERR "%s: failed to create device file\n",
          __func__);
   goto err2;
  }
 }

 return 0;

err2:
 device_unregister(&entry->dev);
 return ret;
err1:
 put_device(&entry->dev);
 return ret;
}
EXPORT_SYMBOL(mISDN_dsp_element_register);

void mISDN_dsp_element_unregister(struct mISDN_dsp_element *elem)
{
 struct dsp_element_entry *entry, *n;

 if (!elem)
  return;

 list_for_each_entry_safe(entry, n, &dsp_elements, list)
  if (entry->elem == elem) {
   device_unregister(&entry->dev);
   return;
  }
 printk(KERN_ERR "%s: element %s not in list.\n", __func__, elem->name);
}
EXPORT_SYMBOL(mISDN_dsp_element_unregister);

int dsp_pipeline_module_init(void)
{
 int err;

 err = class_register(&elements_class);
 if (err)
  return err;

 dsp_hwec_init();

 return 0;
}

void dsp_pipeline_module_exit(void)
{
 struct dsp_element_entry *entry, *n;

 dsp_hwec_exit();

 class_unregister(&elements_class);

 list_for_each_entry_safe(entry, n, &dsp_elements, list) {
  list_del(&entry->list);
  printk(KERN_WARNING "%s: element was still registered: %s\n",
         __func__, entry->elem->name);
  kfree(entry);
 }
}

int dsp_pipeline_init(struct dsp_pipeline *pipeline)
{
 if (!pipeline)
  return -EINVAL;

 INIT_LIST_HEAD(&pipeline->list);

 return 0;
}

static inline void _dsp_pipeline_destroy(struct dsp_pipeline *pipeline)
{
 struct dsp_pipeline_entry *entry, *n;

 list_for_each_entry_safe(entry, n, &pipeline->list, list) {
  list_del(&entry->list);
  if (entry->elem == dsp_hwec)
   dsp_hwec_disable(container_of(pipeline, struct dsp,
            pipeline));
  else
   entry->elem->free(entry->p);
  kfree(entry);
 }
}

void dsp_pipeline_destroy(struct dsp_pipeline *pipeline)
{

 if (!pipeline)
  return;

 _dsp_pipeline_destroy(pipeline);
}

int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg)
{
 int found = 0;
 char *dup, *next, *tok, *name, *args;
 struct dsp_element_entry *entry, *n;
 struct dsp_pipeline_entry *pipeline_entry;
 struct mISDN_dsp_element *elem;

 if (!pipeline)
  return -EINVAL;

 if (!list_empty(&pipeline->list))
  _dsp_pipeline_destroy(pipeline);

 dup = next = kstrdup(cfg, GFP_ATOMIC);
 if (!dup)
  return 0;
 while ((tok = strsep(&next, "|"))) {
  if (!strlen(tok))
   continue;
  name = strsep(&tok, "(");
  args = strsep(&tok, ")");
  if (args && !*args)
   args = NULL;

  list_for_each_entry_safe(entry, n, &dsp_elements, list)
   if (!strcmp(entry->elem->name, name)) {
    elem = entry->elem;

    pipeline_entry = kmalloc(sizeof(struct
        dsp_pipeline_entry), GFP_ATOMIC);
    if (!pipeline_entry) {
     printk(KERN_ERR "%s: failed to add "
            "entry to pipeline: %s (out of "
            "memory)\n", __func__, elem->name);
     goto _out;
    }
    pipeline_entry->elem = elem;

    if (elem == dsp_hwec) {
     /* This is a hack to make the hwec
   available as a pipeline module */

     dsp_hwec_enable(container_of(pipeline,
             struct dsp, pipeline), args);
     list_add_tail(&pipeline_entry->list,
            &pipeline->list);
    } else {
     pipeline_entry->p = elem->new(args);
     if (pipeline_entry->p) {
      list_add_tail(&pipeline_entry->
             list, &pipeline->list);
     } else {
      printk(KERN_ERR "%s: failed "
             "to add entry to pipeline: "
             "%s (new() returned NULL)\n",
             __func__, elem->name);
      kfree(pipeline_entry);
     }
    }
    found = 1;
    break;
   }

  if (found)
   found = 0;
  else
   printk(KERN_ERR "%s: element not found, skipping: "
          "%s\n", __func__, name);
 }

_out:
 if (!list_empty(&pipeline->list))
  pipeline->inuse = 1;
 else
  pipeline->inuse = 0;

 kfree(dup);
 return 0;
}

void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data, int len)
{
 struct dsp_pipeline_entry *entry;

 if (!pipeline)
  return;

 list_for_each_entry(entry, &pipeline->list, list)
  if (entry->elem->process_tx)
   entry->elem->process_tx(entry->p, data, len);
}

void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len,
        unsigned int txlen)
{
 struct dsp_pipeline_entry *entry;

 if (!pipeline)
  return;

 list_for_each_entry_reverse(entry, &pipeline->list, list)
  if (entry->elem->process_rx)
   entry->elem->process_rx(entry->p, data, len, txlen);
}

Messung V0.5
C=96 H=94 G=94

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge