GFFMPEG系统结构简介

来源:互联网 发布:打字淘宝兼职是真的吗 编辑:程序博客网 时间:2024/05/17 01:17

FFMPEG系统结构


主要接口

(1) int av_open_input_file(AVFormatContext **ic_ptr, const char
*filename,
                      AVInputFormat *fmt,
                      int buf_size,
                      AVFormatParameters *ap)
{
    int err, probe_size;
   AVProbeData probe_data, *pd =&probe_data;

//此结构中成员包括:数据操作,缓冲区块等(读取的数据先存入此结构中的缓冲区)
    ByteIOContext *pb = NULL;                      

    pd->filename = "";
    if (filename)
        pd->filename = filename;
    pd->buf = NULL;
    pd->buf_size = 0;

    if (!fmt)
    {
        /* guess format if no file can be opened*/
        fmt = av_probe_input_format(pd, 0);
    }

    /* Do not open file if the format does not need it. XXX: specific
       hack needed to handle RTSP/TCP */
    if (!fmt || !(fmt->flags & AVFMT_NOFILE))
    {
        /* if no file needed do not try to openone */
        //根据filename中协议头,准备相应的网络连接,并初始化pb结构体变量
        if ((err=url_fopen(&pb, filename, URL_RDONLY)) < 0)
        {
            goto fail;
        }
        if (buf_size > 0)
        {
            url_setbufsize(pb,buf_size);
        }

        for (probe_size= PROBE_BUF_MIN;probe_size<=PROBE_BUF_MAX      &&!fmt; probe_size<<=1)
        {
            int score= probe_size <PROBE_BUF_MAX ? AVPROBE_SCORE_MAX/4 : 0;
            /* read probe data */
            pd->buf=av_realloc(pd->buf, probe_size + AVPROBE_PADDING_SIZE);

            //从ByteIOContext中获取数据
            pd->buf_size = get_buffer(pb, pd->buf, probe_size);
           memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE);
            if (url_fseek(pb, 0,SEEK_SET) < 0)
            {
               url_fclose(pb);
                if (url_fopen(&pb,filename, URL_RDONLY) < 0)
                {
                   pb = NULL;
                   err = AVERROR(EIO);
                    gotofail;
                }
            }

            //解析获取的数据
            fmt = av_probe_input_format2(pd, 1, &score);
        }
        av_freep(&pd->buf);
    }

    /* if still no format found, error */
    if (!fmt)
    {
        err = AVERROR_NOFMT;
        goto fail;
    }

    /* check filename in case an image number is expected */
    if (fmt->flags & AVFMT_NEEDNUMBER)
    {
        if (!av_filename_number_test(filename))
        {
            err = AVERROR_NUMEXPECTED;
            goto fail;
        }
}

    err = av_open_input_stream(ic_ptr, pb, filename, fmt, ap);
    if (err)
        goto fail;
    return 0;
fail:
    av_freep(&pd->buf);
    if (pb)
        url_fclose(pb);
    *ic_ptr = NULL;
    return err;

}


(1.1)int url_fopen(ByteIOContext **s, const char *filename, int flags)
{
    URLContext *h;                               //
    int err;
   
//根据filename中协议头,来初始化初始化URLContext变量,并进行
//相应的网络连接
    err = url_open(&h,filename, flags);
    if (err < 0)
        return err;

    //创建并初始化ByteIOContext变量
    err = url_fdopen(s,h);
    if (err < 0)
    {
        url_close(h);
        return err;
    }
    return 0;
}


(1.2)int url_open(URLContext **puc, const char *filename, int flags)
{
    URLProtocol *up;
    const char *p;
    char proto_str[128], *q;

    p = filename;
q = proto_str;

//----解析出协议头(如HTTP,TCP)--------//
    while (*p != '\0' && *p != ':')
    {
        /* protocols can only contain alphabeticchars */
        if (!isalpha(*p))
            goto file_proto;
        if ((q - proto_str) <sizeof(proto_str) - 1)
            *q++ = *p;
        p++;
}

    /* if the protocol has length 1, we consider it is a dos drive */
    if (*p == '\0' || is_dos_path(filename))
    {
file_proto:
        strcpy(proto_str, "file");
    }
    else
    {
        *q = '\0';
    }

//遍历URLProtocol全局指针变量链表(这个在av_register_all()中预先
//准备好了), 根据协议头找到对应的协议URLProtocol变量, 再创建并初始化URLContext,然后进行相应的网络连接(如TCP会去连接相应的服务器)
    up = first_protocol;
    while (up != NULL)
    {
        if (!strcmp(proto_str, up->name))
            return url_open_protocol(puc, up, filename, flags);
        up = up->next;
    }
    *puc = NULL;
    return AVERROR(ENOENT);
}

 


(1.3)int url_fdopen(ByteIOContext **s, URLContext *h)
{
    uint8_t *buffer;
    int buffer_size, max_packet_size;

    //设置缓冲块大小(默认值IO_BUFFER_SIZE:32768)
    max_packet_size = url_get_max_packet_size(h);
    if (max_packet_size)
    {
        buffer_size = max_packet_size; /* no needto bufferize more than one packet */
    }
    else
    {
        buffer_size = IO_BUFFER_SIZE;
}

//创建缓冲块
    buffer = av_malloc(buffer_size);
    if (!buffer)
        return AVERROR(ENOMEM);

    //创建ByteIOContext
    *s = av_mallocz(sizeof(ByteIOContext));
    if (!*s)
    {
        av_free(buffer);
        return AVERROR(ENOMEM);
    }

    //初始化ByteIOContext,如缓冲块大小,读写等操作函数指针
    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;
    }
    return 0;
}


(1.4) int get_buffer(ByteIOContext *s, unsigned char *buf, int size)
{
    int len, size1;
    size1 = size;
    while (size > 0)
{
    //缓冲块中还没被读取的数据量
        len = s->buf_end - s->buf_ptr;
        if (len > size)
            len = size;
        if (len == 0)
        {
            if (size >s->buffer_size && !s->update_checksum)
            {
                if(s->read_packet)
                   len = s->read_packet(s->opaque, buf, size);
                if (len <=0)
                {
                   /* do not modify buffer if EOF reached so that a seek backcan
                   be done without rereading data */
                   s->eof_reached = 1;
                   if (len<0)
                       s->error= len;
                   break;
                }
                else
                {
                   s->pos += len;
                   size -= len;
                   buf += len;
                   s->buf_ptr = s->buffer;
                   s->buf_end = s->buffer/* + len*/;
                }
            }
            else
            {
                //根据ByteIOContext先初始的成员变量,从文件或网络源获取数据
//后COPY到缓冲块中,实际的操作由先初始化的URLProtocol变量
//中成员方法来完成(如url_read,url_seek等)
               fill_buffer(s);
                len =s->buf_end - s->buf_ptr;
                if (len == 0)
                   break;
            }
        }
        else                               //直接从缓冲中获取数据
        {
            memcpy(buf, s->buf_ptr,len);
            buf += len;
            s->buf_ptr += len;
            size -= len;
        }
    }
    return size1 - size;
}

 

(1.5) 识别文件格式并相应的Demuxer

AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int*score_max)

 

 

 

 

(2)  AVCodec *avcodec_find_decoder(enumAVCodecID id)

 

(3) int avcodec_decode_video2(AVCodecContext*avctx, AVFrame *picture, int *got_picture_ptr, const AVPacket *avpkt)

 

(4) int avcodec_decode_audio4(AVCodecContext*avctx, AVFrame *frame, int *got_frame_ptr, const AVPacket *avpkt)

 

(5)  intsws_scale(struct SwsContext *c, const uint8_t * const srcSlice[],const intsrcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[],const intdstStride[])

 

(6) int swr_convert(struct SwrContext *s,uint8_t *out_arg[SWR_CH_MAX], int out_count, const uint8_t *in_arg[SWR_CH_MAX], int  in_count)


0 0
原创粉丝点击