如何写一个处理多媒体的中间库
这里实现一个简单的多媒体数据流的处理库,它是以Filter的思想来实现的,通过Filter可以实现多路数据采集,处理和输出;
一. 如何实现一个filter
1.定义一个Filter descripter 结构,它包含了Filter的主要属性和行为;
typedef struct McFilterDesc{ McFilterId id; const char* name; const char* text; McFilterCategory category; const char* encFormat; int ninputs; int noutputs; McFilterFunc init; McFilterFunc preprocess; McFilterFunc process; McFilterFunc postProcess; McFilterFunc uninit; McFilterMethod* methods; }UC_McFilterDesc;
2. 定义Filter结构体
struct McFilter{ UC_McFilterDesc* desc; pthread_mutex_t lock; struct McQueue **inputs; struct McQueue **outputs; McFilterNotifyFunc notify; void* notifyUd; void* data; struct McTicker* ticker; uint32_t lastTick; bool seen; };
3. 根据Filter descripter 创建Filter 实例
UC_McFilter* mc_filter_new_from_desc(UC_McFilterDesc* desc){ UC_McFilter* filter; filter = (UC_McFilter*)malloc(sizeof(UC_McFilter)); pthread_mutex_init(&filter->lock, NULL); filter->desc = desc; if(desc->ninputs > 0) filter->inputs = (UC_McQueue**)malloc(sizeof(UC_McQueue*) * desc->ninputs); if(desc->noutputs > 0) filter->outputs = (UC_McQueue**)malloc(sizeof(UC_McQueue*) * desc->noutputs); if(desc->init != NULL) desc->init(filter); return filter; }
二. 将创建的Filter 链接起来
UC_McQueue* mc_queue_new(UC_McFilter* filter1, int pin1, UC_McFilter* filter2, int pin2){ UC_McQueue* queue = (UC_McQueue*)malloc(sizeof(UC_McQueue)); uc_queue_init(&queue->q); queue->prev.filter = filter1; queue->prev.pin = pin1; queue->next.filter = filter2; queue->next.pin = pin2; return queue; } int mc_filter_link(UC_McFilter* filter1, int pin1, UC_McFilter* filter2, int pin2){ UC_McQueue* queue; queue = mc_queue_new(filter1, pin1, filter2, pin2); filter1->outputs[pin1] = queue; filter2->inputs[pin2] = queue; return 0; }
三. 将Filter链表加入运行表中
1. 创建Ticker结构,并启动运行线程
struct McTicker{ pthread_mutex_t lock; pthread_cond_t cond; pthread_t thread; UC_McList* execList; int interval; int execId; uint32_t ticks; uint64_t time; bool run; }; typedef struct McTicker UC_McTicker; static void ticker_start(UC_McTicker* ticker){ ticker->run = TRUE; pthread_create(&ticker->thread, NULL, ticker_run, ticker); } static void ticker_init(UC_McTicker* ticker){ pthread_mutex_init(&ticker->lock, NULL); pthread_cond_init(&ticker->cond, NULL); ticker->execList = NULL; ticker->ticks = 1; ticker->time = 0; ticker->interval = 10; ticker->run = FALSE; ticker->execId = 0; ticker_start(ticker); }
2. 将source filter 加入到Ticker的execList中
int mc_ticker_attach(UC_McTicker* ticker, UC_McFilter* filter){ UC_McList* sources = NULL; UC_McList* filters = NULL; UC_McList* iter; if(filter->ticker != NULL){ printf("Filter %s had beeb scheded\n", filter->desc->name); return 0; } printf("%s is invoked\n", __FUNCTION__); ticker_find_filters(&filters, filter); sources = ticker_get_sources(filters); //printf("%s is invoked 2\n", __FUNCTION__); if(sources == NULL){ mc_list_free(filters); return -1; } //printf("%s is invoked 3\n", __FUNCTION__); for(iter = filters; iter != NULL; iter = iter->next){ mc_filter_preprocess((UC_McFilter*)iter->data, ticker); } //printf("%s is invoked 4\n", __FUNCTION__); pthread_mutex_lock(&ticker->lock); ticker->execList = mc_list_concat(ticker->execList, sources); pthread_mutex_unlock(&ticker->lock); mc_list_free(filters); printf("%s is invoked exit\n", __FUNCTION__); return 0; }
3. 运行流程图