您的位置:首页 > 理论基础 > 数据结构算法

ffmpeg解析mpeg2ts时的数据结构分析

2013-08-02 11:51 288 查看
FFmpeg对输入数据的接收是通过FIFO实现的。
下面将对UDP实时TS流进行数据结构和流程分析

1. 相关的数据结构的定义
顶层的所有URL数据结构定义

typedef struct URLContext {

const AVClass *av_class; ///< information for av_log(). Set by
url_open().

struct URLProtocol *prot;

int flags;

int is_streamed; /**< true if streamed (no
seek possible), default = false */

int max_packet_size;

/**< if non
zero, the stream is packetized with this max packet size */

void *priv_data;

char *filename; /**< specified
URL */

int is_connected;

} URLContext;

FIFO的定义:

typedef struct AVFifoBuffer {

uint8_t *buffer;

uint8_t *rptr, *wptr, *end;

uint32_t rndx, wndx;

} AVFifoBuffer;

UDP数据结构定义

typedef struct {

int udp_fd;

int ttl;

int buffer_size;

int is_multicast;

int local_port;

int reuse_socket;

struct sockaddr_storage dest_addr;

int dest_addr_len;

int is_connected;

/* Circular Buffer variables for use in UDP
receive code */

int circular_buffer_size;

AVFifoBuffer *fifo;

int circular_buffer_error;

#if HAVE_PTHREADS

pthread_t circular_buffer_thread;

#endif

} UDPContext;

2. 初始化UDP的socket,并接收数据

/* put it in UDP context ,return
non zero if error */

static int udp_open(URLContext *h, const char *uri, int flags)

{

...

UDPContext *s = NULL;

s = av_mallocz(sizeof(UDPContext));

h->priv_data = s;

进行UDP的相关设置;

s->circular_buffer_size = 7*188*65536;

if (!is_output && s->circular_buffer_size)

{

/* start the task going */

s->fifo = av_fifo_alloc(s->circular_buffer_size);

/*

* 启动UDP数据接收线程,

* 使得实时数据的接收和转码并行进行。

*/

if (pthread_create(&s->circular_buffer_thread, NULL, circular_buffer_task, h))

{

av_log(h, AV_LOG_ERROR, "pthread_create
failed\n");

goto fail;

}

}

}

/* 初始化输入数据的FIFO */

void av_fifo_reset(AVFifoBuffer *f)

{

f->wptr = f->rptr = f->buffer;

f->wndx = f->rndx = 0;

}

/*

* 函数功能:

* 从UDP对应的socket中接收数据,

* 并存储到FIFO中

*/

void *circular_buffer_task( void *_URLContext)

{

URLContext *h = _URLContext;

UDPContext *s = h->priv_data;

for ( ; ; )

{

...

/*

* 将从socket s->udp_fd接收到的数据

* 存储到由s->fifo->wptr指定的s->fifo->buffer的位置

*/

len = recv(s->udp_fd, s->fifo->wptr, left, 0);

s->fifo->wptr += len;

/* FIFO的循环使用 */

if (s->fifo->wptr >= s->fifo->end)

s->fifo->wptr = s->fifo->buffer;

s->fifo->wndx += len;

}

}

3. mpeg2-TS解析时的数据使用
函数调用关系图与从FIFO中获取数据的代码

av_demuxer_open()

|

V

mpegts_read_header()

|

V

avio_read()

|

V

ffurl_read()

|

V

int udp_read(URLContext *h, uint8_t *buf, int size)

{

UDPContext *s = h->priv_data;

int ret;

int avail;

fd_set rfds;

struct timeval tv;

if (s->fifo)

{

do

{

/* 查看FIFO中现有多少字节数据可用 */

avail = av_fifo_size(s->fifo);

if (avail)

{

// Maximum amount available

size = FFMIN( avail, size);

/* 将FIFO s->fifo中的数据复制size个字节到buf中 */

av_fifo_generic_read(s->fifo, buf, size, NULL);

return size;

}

else

{ ... }

} while( 1);

}

...

}

4. 总的来说,
UDP的数据(UDPContext)都是通过URLContext的"void *priv_data"以指针的方式来传递;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: