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"以指针的方式来传递;
下面将对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"以指针的方式来传递;
相关文章推荐
- ffmpeg解析mpeg2ts时的数据结构分析
- Ffmpeg解析media容器过程/ ffmpeg 源代码简单分析 : av_read_frame()
- Redis 3.0 源码解析---底层数据结构分析(3)
- ffmpeg分析 之 如何解析mpegts流
- FFmpeg数据结构和库简介和简单分析
- FFmpeg数据结构:AVPacket解析
- 分布式消息队列RocketMQ源码分析之1 -- Topic路由数据结构解析 -- topicRoute与topicPublishInfo与queueId
- 分析ffmpeg解析ts流信息的源码
- FFMpeg之 Mpeg2TS解析
- Redis 3.0 源码解析---底层数据结构分析(4)
- [置顶] FFmpeg数据结构:AVPacket解析
- Redis 3.0 源码解析---底层数据结构分析(2)
- FFMPEG 数据结构分析
- ffmpeg对mpeg2-TS解析的最详细分析
- ffmpeg对mpeg2-TS解析的最详细分析
- 分布式消息队列RocketMQ源码分析之1 -- Topic路由数据结构解析 -- topicRoute与topicPublishInfo与queueId
- Redis 3.0 源码解析---底层数据结构分析(1)
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- ffmpeg对mpeg2-TS解析的最详细分析
- FFmpeg情景分析 1. FFmpeg转码框架解析