ffmpeg分析系列之五(開啟輸入的檔案)

helloxchen發表於2010-11-04
ffmpeg分析系列之五(開啟輸入的檔案)
1. 開啟檔案:

if (!fmt || !(fmt->flags & AVFMT_NOFILE)) {

因 fmt == NULL, 上面成立, 再看下面的程式碼:

ByteIOContext *pb = NULL; // 位元組IO上下文
if ((err=url_fopen(&pb, filename, URL_RDONLY)) < 0) { // 只讀方式開啟輸入的檔案
goto fail;
}
if (buf_size > 0) { // 因 buf_size == 0, 不成立
url_setbufsize(pb, buf_size);

}


進入url_fopen函式:

int url_fopen(ByteIOContext **s, // 輸出引數: 位元組IO上下文
const char *filename, // 檔名
int flags) // 標誌
{
URLContext *h; // URL(統一資源定位)上下文
int err;

err = url_open(&h, filename, flags); // 開啟URL
if (err < 0)
return err;
err = url_fdopen(s, h); // 用URL上下文開啟位元組IO上下文
if (err < 0) {
url_close(h);
return err;
}
return 0;
}


進入url_open函式:

int url_open(URLContext **puc, // 輸出引數: URL上下文

const char *filename, // 檔名

int flags) // 標誌

{
URLProtocol *up;
const char *p;
char proto_str[128], *q;

// 提取協議
p = filename;
q = proto_str;
while (*p != '' && *p != ':') { // 未結束, 並未遇到分隔符':'
if (!isalpha(*p)) // 如果不是英文字母
goto file_proto;
if ((q - proto_str) < sizeof(proto_str) - 1)
*q++ = *p; // 記錄協議字串
p++;
}

if (*p == '' || is_dos_path(filename)) { // 如果上面是因為結束而跳出, 或且
檔名是DOS路徑

file_proto:
strcpy(proto_str, "file"); // 檔案協議
} else {
*q = ''; // 追加結束符
}

up = first_protocol;
while (up != NULL) {
if (!strcmp(proto_str, up->name)) // 協議匹配
return url_open_protocol (puc, up, filename, flags); // 用這個協議開啟URL
up = up->next;
}
*puc = NULL;
return AVERROR(ENOENT);
}


進入url_open_protocol函式:

int url_open_protocol (URLContext **puc, // 輸出引數: URL上下文

struct URLProtocol *up, // URL協議

const char *filename, // 檔名

int flags) // 標誌
{
URLContext *uc;
int err;

// 網路初始化
#if CONFIG_NETWORK
if (!ff_network_init())
return AVERROR(EIO);
#endif

// 分配URL上下文並加上檔名的儲存空間
uc = av_mallocz(sizeof(URLContext) + strlen(filename) + 1);
if (!uc) {
err = AVERROR(ENOMEM);
goto fail;
}

// 初始化URL上下文
#if LIBAVFORMAT_VERSION_MAJOR >= 53
uc->av_class = &urlcontext_class;
#endif

// 記錄檔名
uc->filename = (char *) &uc[1];
strcpy(uc->filename, filename);

uc->prot = up;
// URL協議

uc->flags = flags; // 標誌
uc->is_streamed = 0; // 預設不是流, 可以在up->url_open函式里修改
uc->max_packet_size = 0; //
包最大多大, 預設為0, 可以在up->url_open函式里修改

// 開啟URL
err = up->url_open(uc, filename, flags);
if (err < 0) {
av_free(uc);
goto fail;
}

if( (flags & (URL_WRONLY | URL_RDWR)) // 如果以可寫方式開啟

|| !strcmp(up->name, "file")) // 或且是檔案協議

// 如果不是流並且不可以url_seek

if(!uc->is_streamed && url_seek(uc, 0, SEEK_SET) < 0)
uc->is_streamed= 1; // 強制為流


// 輸出
引數: URL上下文

*puc = uc;
return 0;
fail:
*puc = NULL;
#if CONFIG_NETWORK
ff_network_close();
#endif
return err;
}

先來看看url_get_max_packet_size函式

int url_get_max_packet_size(URLContext *h)
{
return h->max_packet_size; // 包最大多大, 被上面初始化為0
}

進入url_fdopen函式:

int url_fdopen(

ByteIOContext **s, // 輸出引數: 位元組IO上下文

URLContext *h) // URL上下文
{
uint8_t *buffer;
int buffer_size, max_packet_size;

max_packet_size = url_get_max_packet_size(h);
if (max_packet_size) {
buffer_size = max_packet_size;
} else {
buffer_size = IO_BUFFER_SIZE; // 緩衝大小為IO_BUFFER_SIZE
}
buffer = av_malloc(buffer_size); // 分配緩衝
if (!buffer)
return AVERROR(ENOMEM);

*s = av_mallocz(sizeof(ByteIOContext)); // 分配位元組IO上下文

if(!*s) {
av_free(buffer);
return AVERROR(ENOMEM);
}

if (init_put_byte(*s, buffer, buffer_size,
(h->flags & URL_WRONLY || h->flags & URL_RDWR), h,
url_read, url_write, url_seek) < 0) {
av_free(buffer);
av_freep(s);
return AVERROR(EIO);
}
(*s)->is_streamed = h->is_streamed; // 是否為流
(*s)->max_packet_size = max_packet_size; // 包最大多大
if(h->prot) {
(*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause; // 讀暫停函式
(*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek; // 讀seek函式
}
return 0;
}


進入init_put_byte函式:

int init_put_byte(ByteIOContext *s, // 位元組IO上下文
unsigned char *buffer, // 緩衝
int buffer_size, // 緩衝的大小
int write_flag, // 寫標誌
void *opaque, // URL上下文
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), // 讀包
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),// 寫包
int64_t (*seek)(void *opaque, int64_t offset, int whence)) // 調整檔案指標
{
s->buffer = buffer;
s->buffer_size = buffer_size;
s->buf_ptr = buffer;
s->opaque = opaque;
url_resetbuf(s, write_flag ? URL_WRONLY : URL_RDONLY);
s->write_packet = write_packet;
s->read_packet = read_packet;
s->seek = seek;
s->pos = 0;
s->must_flush = 0;
s->eof_reached = 0;
s->error = 0;
s->is_streamed = 0;
s->max_packet_size = 0;
s->update_checksum= NULL;
if(!read_packet && !write_flag){
s->pos = buffer_size;
s->buf_end = s->buffer + buffer_size;
}
s->read_pause = NULL;
s->read_seek = NULL;
return 0;
}

轉自http://blog.chinaunix.net/u3/104564/showart_2369538.html[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24790158/viewspace-1040900/,如需轉載,請註明出處,否則將追究法律責任。

相關文章