FFmpeg源代码简单学习:avformat_close_input()

参考博客:https://blog.csdn.net/leixiaohua1020/article/details/44110683


void avformat_close_input(AVFormatContext **ps)
{
    AVFormatContext *s;
    AVIOContext *pb;

    //“不存在” 直接返回
    if (!ps || !*ps)
        return;

    s  = *ps;
    pb = s->pb;

    //image2是什么格式?为什么要单独处理
    if ((s->iformat && strcmp(s->iformat->name, "image2") && s->iformat->flags & AVFMT_NOFILE) ||
        (s->flags & AVFMT_FLAG_CUSTOM_IO))
        pb = NULL;

    //清理:parse_queue packet_buffer  raw_packet_buffer
    flush_packet_queue(s);

    //read_close为函数指针,具体与iformat相关
    if (s->iformat)
        if (s->iformat->read_close)
            s->iformat->read_close(s);

    //释放AVFormatContext结构体
    avformat_free_context(s);

    *ps = NULL;

    //释放AVIOContext结构体
    avio_close(pb);
}



//==================================
//read_close是一个函数指针,作用是关闭输入流
//此为rtsp_read_close,网络流

static int rtsp_read_close(AVFormatContext *s)
{
    RTSPState *rt = s->priv_data;

    if (!(rt->rtsp_flags & RTSP_FLAG_LISTEN))
        ff_rtsp_send_cmd_async(s, "TEARDOWN", rt->control_uri, NULL);

    ff_rtsp_close_streams(s);
    ff_rtsp_close_connections(s);
    ff_network_close();
    rt->real_setup = NULL;
    av_freep(&rt->real_setup_cache);
    return 0;
}

//====================================================
//flv_read_close关闭文件流
//主要是释放一些关键的指针
static int flv_read_close(AVFormatContext *s)
{
    int i;
    FLVContext *flv = s->priv_data;
    for (i=0; i<FLV_STREAM_TYPE_NB; i++)
        av_freep(&flv->new_extradata[i]);
    av_freep(&flv->keyframe_times);
    av_freep(&flv->keyframe_filepositions);
    return 0;
}

//=====================================================

//avformat_free_context是释放AVFormatContext结构体,及所有的流
void avformat_free_context(AVFormatContext *s)
{
    int i;

    if (!s)
        return;

    if (s->oformat && s->oformat->deinit && s->internal->initialized)
        s->oformat->deinit(s);

    /*    下面是调用了一系列的函数进行释放操作   */
    av_opt_free(s);
    if (s->iformat && s->iformat->priv_class && s->priv_data)
        av_opt_free(s->priv_data);
    if (s->oformat && s->oformat->priv_class && s->priv_data)
        av_opt_free(s->priv_data);

    for (i = 0; i < s->nb_streams; i++)//遍历所有的流并释放
        free_stream(&s->streams[i]);
    s->nb_streams = 0;//number置零

    for (i = 0; i < s->nb_programs; i++) {//遍历所有的programes并释放
        av_dict_free(&s->programs[i]->metadata);
        av_freep(&s->programs[i]->stream_index);
        av_freep(&s->programs[i]);
    }
    s->nb_programs = 0;//置零

    av_freep(&s->programs);
    av_freep(&s->priv_data);

    while (s->nb_chapters--) {//遍历所有的chapters并释放
        av_dict_free(&s->chapters[s->nb_chapters]->metadata);
        av_freep(&s->chapters[s->nb_chapters]);
    }
    av_freep(&s->chapters);
    av_dict_free(&s->metadata);
    av_dict_free(&s->internal->id3v2_meta);
    av_packet_free(&s->internal->pkt);
    av_packet_free(&s->internal->parse_pkt);
    av_freep(&s->streams);
    flush_packet_queue(s);
for (int i = 0; i < count; ++i)
    {
        /* code */
    }    av_freep(&s->internal);
    av_freep(&s->url);
    av_free(s);
}

//================================================================

//avio_close函数的作用:关闭AVIOContext并释放
//仅当avio_open打开了s时有效
int avio_close(AVIOContext *s)
{
    URLContext *h;

    if (!s)
        return 0;

    avio_flush(s);//调用函数avio_flush
    h         = s->opaque;
    s->opaque = NULL;

    av_freep(&s->buffer);
    if (s->write_flag)
        av_log(s, AV_LOG_VERBOSE, "Statistics: %d seeks, %d writeouts\n", s->seek_count, s->writeout_count);
    else
        av_log(s, AV_LOG_VERBOSE, "Statistics: %"PRId64" bytes read, %d seeks\n", s->bytes_read, s->seek_count);
    av_opt_free(s);

    avio_context_free(&s);

    //调用函数ffurl_close
    return ffurl_close(h);
}

//========================================================

//ffurl_close函数调用ffurl_closep
//功能:关闭URLContext并释放


int ffurl_closep(URLContext **hh)
{
    URLContext *h= *hh;
    int ret = 0;
    if (!h)
        return 0;     /* can happen when ffurl_open fails */

    if (h->is_connected && h->prot->url_close)
        ret = h->prot->url_close(h);//url_close函数指针,与protocol相关
    // prot: const struct URLProtocol *prot;
#if CONFIG_NETWORK
    if (h->prot->flags & URL_PROTOCOL_FLAG_NETWORK)
        ff_network_close();//network
#endif
    if (h->prot->priv_data_size) {
        if (h->prot->priv_data_class)
            av_opt_free(h->priv_data);
        av_freep(&h->priv_data);
    }
    av_opt_free(h);
    av_freep(hh);
    return ret;
}

 

posted @ 2021-04-16 14:20  Keep_Silent  阅读(24)  评论(0编辑  收藏  举报