• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

            路漫漫,長修遠,我們不能沒有錢
            隨筆 - 173, 文章 - 0, 評論 - 257, 引用 - 0
            數據加載中……

            ffmpeg分析系列之七(打開輸入的流)

            err = av_open_input_stream(ic_ptr, pb, filename, fmt, ap);



            int av_open_input_stream(

            AVFormatContext **ic_ptr// 輸出參數: 格式上下文
            ByteIOContext *pb, 
            // 字節IO上下文

            const char *filename// 文件名
            AVInputFormat *fmt, 
            // 輸入的格式

            AVFormatParameters *ap// 格式參數, 調用時為NULL
            {
                int err;
                AVFormatContext *ic;
                AVFormatParameters default_ap;

                 // 使用缺省的格式參數
                if(!ap){
                    ap=&default_ap;
                    memset(ap, 0, sizeof(default_ap));
                }

                if(!ap->prealloced_context)
                    ic = avformat_alloc_context()// 分配格式上下文
                else
                    ic = *ic_ptr;
                if (!ic) {
                    err = AVERROR(ENOMEM);
                    goto fail;
                }

                // 初始化格式上下文
                ic->iformat = fmt// 格式
                ic->pb = pb// 字節IO上下文
                ic->duration = AV_NOPTS_VALUE;
                ic->start_time = AV_NOPTS_VALUE;
                av_strlcpy(ic->filename, filename, sizeof(ic->filename))// 文件名

                /* 分配私有數據 */
                if (fmt->priv_data_size > 0) {
                    ic->priv_data = av_mallocz(fmt->priv_data_size);
                    if (!ic->priv_data) {
                        err = AVERROR(ENOMEM);
                        goto fail;
                    }
                } else {
                    ic->priv_data = NULL;
                }

                // 讀首部
                if (ic->iformat->read_header) {
                    err = ic->iformat->read_header(ic, ap);
                    if (err < 0)
                        goto fail;
                }

                // 獲得數據偏移
                if (pb && !ic->data_offset)
                    ic->data_offset = url_ftell(ic->pb);

            #if LIBAVFORMAT_VERSION_MAJOR < 53
                ff_metadata_demux_compat(ic);
            #endif

                // 原始的包緩沖剩余的大小
                ic->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;

                // 輸出參數: 格式上下文

                *ic_ptr = ic;
                return 0;

            }


            具體請參看

            ffmpeg分析系列之三(輸入輸出格式)


            格式上下文結構:

            typedef struct AVFormatContext {
                const AVClass *av_class; /**< Set by avformat_alloc_context. */

                // 省略部分內容
            }


            AV類結構:

            typedef struct {
                
            /**
                 * The name of the class; usually it is the same name as the
                 * context structure type to which the AVClass is associated.
                 */

                const char* class_name;

                
            /**
                 * A pointer to a function which returns the name of a context
                 * instance ctx associated with the class.
                 */

                const char* (*item_name)(void* ctx);

                
            /**
                 * a pointer to the first option specified in the class if any or NULL
                 *
                 * @see av_set_default_options()
                 */

                const struct AVOption *option;

                
            /**
                 * LIBAVUTIL_VERSION with which this structure was created.
                 * This is used to allow fields to be added without requiring major
                 * version bumps everywhere.
                 */


                int version;
            } AVClass;



            進入avformat_alloc_context函數, 分配格式上下文:

            AVFormatContext *avformat_alloc_context(void)
            {
                AVFormatContext *ic;
                ic = av_malloc(sizeof(AVFormatContext));
                if (!ic) return ic;
                avformat_get_context_defaults(ic);
                ic->av_class = &av_format_context_class;
                return ic;
            }


            static const AVClass av_format_context_class = { "AVFormatContext", format_to_name, options,LIBAVUTIL_VERSION_INT };


            進入avformat_get_context_defaults函數, 格式獲得缺省上下文:

            static void avformat_get_context_defaults(AVFormatContext *s)
            {
                memset(s, 0, sizeof(AVFormatContext));
                s->av_class = &av_format_context_class;
                av_opt_set_defaults(s);
            }


             

            av_opt_set_defaults函數就不分析了. 

            下面繼續分析:

            err = ic->iformat->read_header(ic, ap)


            以輸入格式為libavformat/raw.c下的h264_demuxer為例:

            AVInputFormat h264_demuxer = {
                "h264",
                NULL_IF_CONFIG_SMALL("raw H.264 video format"),
                0,
                h264_probe,
                video_read_header,
                ff_raw_read_partial_packet,
                .flags= AVFMT_GENERIC_INDEX,
                .extensions = "h26l,h264,264", 
            //FIXME remove after writing mpeg4_probe

                .value = CODEC_ID_H264,
            };



            會調用video_read_header函數:

            static int video_read_header(AVFormatContext *s,
                                         AVFormatParameters *ap)
            {
                AVStream *st;

                st = av_new_stream(s, 0)// 格式上下文增加一個流
                if (!st)
                    return AVERROR(ENOMEM);


                 // 初始化流
                st->codec->codec_type = AVMEDIA_TYPE_VIDEO
            // 編碼編碼器類型
                st->codec->codec_id = s->iformat->value// 為 CODEC_ID_H264
                st->need_parsing = AVSTREAM_PARSE_FULL// 需要全分析

                /* for MJPEG, specify frame rate */
                /* for MPEG-4 specify it, too (most MPEG-4 streams do not have the fixed_vop_rate set ...)*/
                if (ap->time_base.num) {

                    st->codec->time_base= ap->time_base;
                } else if ( st->codec->codec_id == CODEC_ID_MJPEG ||
                            st->codec->codec_id == CODEC_ID_MPEG4 ||
                            st->codec->codec_id == CODEC_ID_DIRAC ||
                            st->codec->codec_id == CODEC_ID_DNXHD ||
                            st->codec->codec_id == CODEC_ID_H264) {
                    st->codec->time_base= (AVRational){1,25}// 設置時基
                }
                av_set_pts_info(st, 64, 1, 1200000)// 設置PTS(顯示時間截)信息

                return 0;
            }


            進入av_new_stream函數:

            AVStream *av_new_stream(AVFormatContext *s, int id)
            {
                AVStream *st;
                int i;

                // 格式上下文不能太多流
                if (s->nb_streams >= MAX_STREAMS)
                    return NULL;

                // 分配一個流
                st = av_mallocz(sizeof(AVStream));
                if (!st)
                    return NULL;

                // 分配解碼器上下文
                st->codec= avcodec_alloc_context();
                if (s->iformat) {
                    /* no default bitrate if decoding */
                    st->codec->bit_rate = 0;
                }
                st->index = s->nb_streams// 流索引
                st->id = id// ID, 為0
                st->start_time = AV_NOPTS_VALUE// 開始時間
                st->duration = AV_NOPTS_VALUE;
                    
            /* we set the current DTS to 0 so that formats without any timestamps
                       but durations get some timestamps, formats with some unknown
                       timestamps have their first few packets buffered and the
                       timestamps corrected before they are returned to the user */

                st->cur_dts = 0// 當前的解碼時間截
                st->first_dts = AV_NOPTS_VALUE// 起始的解碼時間截
                st->probe_packets = MAX_PROBE_PACKETS// 探測的最大包數

                /* default pts setting is MPEG-like */

                av_set_pts_info(st, 33, 1, 90000)// 設置PTS顯示時間截信息
                st->last_IP_pts = AV_NOPTS_VALUE
                for(i=0; i<MAX_REORDER_DELAY+1; i++)
                    st->pts_buffer[i]= AV_NOPTS_VALUE;
                st->reference_dts = AV_NOPTS_VALUE;

                st->sample_aspect_ratio = (AVRational){0,1};

                s->streams[s->nb_streams++] = st// 記錄流, 同時流數加一
                return st;
            }


            分配編碼解碼器上下文:
             

            static const AVClass av_codec_context_class = { "AVCodecContext", context_to_name, options,LIBAVUTIL_VERSION_INT };


            void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType codec_type){
                int flags=0;
                memset(s, 0, sizeof(AVCodecContext));

                s->av_class= &av_codec_context_class;

                s->codec_type = codec_type;
                if(codec_type == AVMEDIA_TYPE_AUDIO)
                    flags= AV_OPT_FLAG_AUDIO_PARAM;
                else if(codec_type == AVMEDIA_TYPE_VIDEO)
                    flags= AV_OPT_FLAG_VIDEO_PARAM;
                else if(codec_type == AVMEDIA_TYPE_SUBTITLE)
                    flags= AV_OPT_FLAG_SUBTITLE_PARAM;
                av_opt_set_defaults2(s, flags, flags);

                s->time_base= (AVRational){0,1};
                s->get_buffer= avcodec_default_get_buffer;
                s->release_buffer= avcodec_default_release_buffer;
                s->get_format= avcodec_default_get_format;
                s->execute= avcodec_default_execute;
                s->execute2= avcodec_default_execute2;
                s->sample_aspect_ratio= (AVRational){0,1};
                s->pix_fmt= PIX_FMT_NONE;
                s->sample_fmt= SAMPLE_FMT_NONE;

                s->palctrl = NULL;
                s->reget_buffer= avcodec_default_reget_buffer;
                s->reordered_opaque= AV_NOPTS_VALUE;
            }

            AVCodecContext *avcodec_alloc_context2(enum AVMediaType codec_type){
                AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));

                if(avctx==NULL) return NULL;

                avcodec_get_context_defaults2(avctx, codec_type);

                return avctx;
            }

            void avcodec_get_context_defaults(AVCodecContext *s){
                avcodec_get_context_defaults2(s, AVMEDIA_TYPE_UNKNOWN);
            }

            AVCodecContext *avcodec_alloc_context(void){
                return avcodec_alloc_context2(AVMEDIA_TYPE_UNKNOWN);
            }

            @import url(http://m.shnenglu.com/cutesoft_client/cuteeditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);

            posted on 2012-12-14 01:47 Khan 閱讀(2202) 評論(0)  編輯 收藏 引用 所屬分類: GCC/G++周邊技術

            AV无码久久久久不卡蜜桃| 日韩久久久久久中文人妻| 香蕉99久久国产综合精品宅男自 | 亚洲综合熟女久久久30p| 久久国产精品成人影院| 国产精品无码久久综合网| 久久无码AV中文出轨人妻| 亚洲国产精品久久久久婷婷老年| 久久综合精品国产一区二区三区| 无遮挡粉嫩小泬久久久久久久| 国产精品久久久天天影视香蕉 | 国产叼嘿久久精品久久| 久久婷婷五月综合97色直播| 99久久精品免费看国产| 伊人久久大香线焦AV综合影院| 91精品国产91热久久久久福利| 久久精品aⅴ无码中文字字幕不卡| 久久精品国产一区| 亚洲中文字幕久久精品无码喷水 | 久久丫精品国产亚洲av不卡| 一级女性全黄久久生活片免费 | 久久精品久久久久观看99水蜜桃 | 日本欧美国产精品第一页久久| 久久99热只有频精品8| 久久人与动人物a级毛片| 无码任你躁久久久久久老妇| 国产日韩欧美久久| 精品国产乱码久久久久久浪潮| 久久发布国产伦子伦精品| 99久久精品免费看国产一区二区三区 | 中文国产成人精品久久不卡| 久久精品国产亚洲5555| 国产2021久久精品| 国产精品久久久久一区二区三区 | 亚洲色婷婷综合久久| 伊人久久大香线蕉综合5g| 狠狠色综合久久久久尤物| 99久久国产综合精品网成人影院| 久久久91精品国产一区二区三区 | 久久亚洲国产精品成人AV秋霞| 久久影视综合亚洲|