utils.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 2,066 行 · 第 1/5 页

C
2,066
字号
    if (ret < 0)        return ret;  }  if(!has_codec_parameters(st->codec)){    switch(st->codec->codec_type) {    case CODEC_TYPE_VIDEO:        ret = avcodec_decode_video(st->codec, &picture,                                   &got_picture, (uint8_t *)data, size);        break;    case CODEC_TYPE_AUDIO:        data_size = FFMAX(size, AVCODEC_MAX_AUDIO_FRAME_SIZE);        samples = av_malloc(data_size);        if (!samples)            goto fail;        ret = avcodec_decode_audio2(st->codec, samples,                                    &data_size, (uint8_t *)data, size);        av_free(samples);        break;    default:        break;    }  } fail:    return ret;}static int set_codec_from_probe_data(AVStream *st, AVProbeData *pd, int score){    AVInputFormat *fmt;    fmt = av_probe_input_format2(pd, 1, &score);    if (fmt) {        if (strncmp(fmt->name, "mp3", 3) == 0)            st->codec->codec_id = CODEC_ID_MP3;        else if (strncmp(fmt->name, "ac3", 3) == 0)            st->codec->codec_id = CODEC_ID_AC3;    }    return !!fmt;}unsigned int codec_get_tag(const AVCodecTag *tags, int id){    while (tags->id != CODEC_ID_NONE) {        if (tags->id == id)            return tags->tag;        tags++;    }    return 0;}enum CodecID codec_get_id(const AVCodecTag *tags, unsigned int tag){    int i;    for(i=0; tags[i].id != CODEC_ID_NONE;i++) {        if(tag == tags[i].tag)            return tags[i].id;    }    for(i=0; tags[i].id != CODEC_ID_NONE; i++) {        if(   toupper((tag >> 0)&0xFF) == toupper((tags[i].tag >> 0)&0xFF)           && toupper((tag >> 8)&0xFF) == toupper((tags[i].tag >> 8)&0xFF)           && toupper((tag >>16)&0xFF) == toupper((tags[i].tag >>16)&0xFF)           && toupper((tag >>24)&0xFF) == toupper((tags[i].tag >>24)&0xFF))            return tags[i].id;    }    return CODEC_ID_NONE;}unsigned int av_codec_get_tag(const AVCodecTag *tags[4], enum CodecID id){    int i;    for(i=0; tags && tags[i]; i++){        int tag= codec_get_tag(tags[i], id);        if(tag) return tag;    }    return 0;}enum CodecID av_codec_get_id(const AVCodecTag *tags[4], unsigned int tag){    int i;    for(i=0; tags && tags[i]; i++){        enum CodecID id= codec_get_id(tags[i], tag);        if(id!=CODEC_ID_NONE) return id;    }    return CODEC_ID_NONE;}/* absolute maximum size we read until we abort */#define MAX_READ_SIZE        5000000#define MAX_STD_TIMEBASES (60*12+5)static int get_std_framerate(int i){    if(i<60*12) return i*1001;    else        return ((int[]){24,30,60,12,15})[i-60*12]*1000*12;}int av_find_stream_info(AVFormatContext *ic){    int i, count, ret, read_size, j;    AVStream *st;    AVPacket pkt1, *pkt;    int64_t last_dts[MAX_STREAMS];    int duration_count[MAX_STREAMS]={0};    double (*duration_error)[MAX_STD_TIMEBASES];    offset_t old_offset = url_ftell(&ic->pb);    int64_t codec_info_duration[MAX_STREAMS]={0};    int codec_info_nb_frames[MAX_STREAMS]={0};    AVProbeData probe_data[MAX_STREAMS];    int codec_identified[MAX_STREAMS]={0};    duration_error = av_mallocz(MAX_STREAMS * sizeof(*duration_error));    if (!duration_error) return AVERROR(ENOMEM);    for(i=0;i<ic->nb_streams;i++) {        st = ic->streams[i];        if(st->codec->codec_type == CODEC_TYPE_VIDEO){/*            if(!st->time_base.num)                st->time_base= */            if(!st->codec->time_base.num)                st->codec->time_base= st->time_base;        }        //only for the split stuff        if (!st->parser) {            st->parser = av_parser_init(st->codec->codec_id);            if(st->need_parsing == AVSTREAM_PARSE_HEADERS && st->parser){                st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;            }        }    }    for(i=0;i<MAX_STREAMS;i++){        last_dts[i]= AV_NOPTS_VALUE;    }    memset(probe_data, 0, sizeof(probe_data));    count = 0;    read_size = 0;    for(;;) {        /* check if one codec still needs to be handled */        for(i=0;i<ic->nb_streams;i++) {            st = ic->streams[i];            if (!has_codec_parameters(st->codec))                break;            /* variable fps and no guess at the real fps */            if(   (st->codec->time_base.den >= 101LL*st->codec->time_base.num || st->codec->codec_id == CODEC_ID_MPEG2VIDEO)               && duration_count[i]<20 && st->codec->codec_type == CODEC_TYPE_VIDEO)                break;            if(st->parser && st->parser->parser->split && !st->codec->extradata)                break;            if(st->first_dts == AV_NOPTS_VALUE)                break;        }        if (i == ic->nb_streams) {            /* NOTE: if the format has no header, then we need to read               some packets to get most of the streams, so we cannot               stop here */            if (!(ic->ctx_flags & AVFMTCTX_NOHEADER)) {                /* if we found the info for all the codecs, we can stop */                ret = count;                break;            }        }        /* we did not get all the codec info, but we read too much data */        if (read_size >= MAX_READ_SIZE) {            ret = count;            break;        }        /* NOTE: a new stream can be added there if no header in file           (AVFMTCTX_NOHEADER) */        ret = av_read_frame_internal(ic, &pkt1);        if (ret < 0) {            /* EOF or error */            ret = -1; /* we could not have all the codec parameters before EOF */            for(i=0;i<ic->nb_streams;i++) {                st = ic->streams[i];                if (!has_codec_parameters(st->codec)){                    char buf[256];                    avcodec_string(buf, sizeof(buf), st->codec, 0);                    av_log(ic, AV_LOG_INFO, "Could not find codec parameters (%s)\n", buf);                } else {                    ret = 0;                }            }            break;        }        pkt= add_to_pktbuf(ic, &pkt1);        if(av_dup_packet(pkt) < 0)            return AVERROR(ENOMEM);        read_size += pkt->size;        st = ic->streams[pkt->stream_index];        if(codec_info_nb_frames[st->index]>1)            codec_info_duration[st->index] += pkt->duration;        if (pkt->duration != 0)            codec_info_nb_frames[st->index]++;        {            int index= pkt->stream_index;            int64_t last= last_dts[index];            int64_t duration= pkt->dts - last;            if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && duration>0){                double dur= duration * av_q2d(st->time_base);//                if(st->codec->codec_type == CODEC_TYPE_VIDEO)//                    av_log(NULL, AV_LOG_ERROR, "%f\n", dur);                if(duration_count[index] < 2)                    memset(duration_error, 0, MAX_STREAMS * sizeof(*duration_error));                for(i=1; i<MAX_STD_TIMEBASES; i++){                    int framerate= get_std_framerate(i);                    int ticks= lrintf(dur*framerate/(1001*12));                    double error= dur - ticks*1001*12/(double)framerate;                    duration_error[index][i] += error*error;                }                duration_count[index]++;            }            if(last == AV_NOPTS_VALUE || duration_count[index]<=1)                last_dts[pkt->stream_index]= pkt->dts;            if (st->codec->codec_id == CODEC_ID_NONE) {                AVProbeData *pd = &(probe_data[st->index]);                pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE);                memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size);                pd->buf_size += pkt->size;                memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE);            }        }        if(st->parser && st->parser->parser->split && !st->codec->extradata){            int i= st->parser->parser->split(st->codec, pkt->data, pkt->size);            if(i){                st->codec->extradata_size= i;                st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);                memcpy(st->codec->extradata, pkt->data, st->codec->extradata_size);                memset(st->codec->extradata + i, 0, FF_INPUT_BUFFER_PADDING_SIZE);            }        }        /* if still no information, we try to open the codec and to           decompress the frame. We try to avoid that in most cases as           it takes longer and uses more memory. For MPEG4, we need to           decompress for Quicktime. */        if (!has_codec_parameters(st->codec) /*&&            (st->codec->codec_id == CODEC_ID_FLV1 ||             st->codec->codec_id == CODEC_ID_H264 ||             st->codec->codec_id == CODEC_ID_H263 ||             st->codec->codec_id == CODEC_ID_H261 ||             st->codec->codec_id == CODEC_ID_VORBIS ||             st->codec->codec_id == CODEC_ID_MJPEG ||             st->codec->codec_id == CODEC_ID_PNG ||             st->codec->codec_id == CODEC_ID_PAM ||             st->codec->codec_id == CODEC_ID_PGM ||             st->codec->codec_id == CODEC_ID_PGMYUV ||             st->codec->codec_id == CODEC_ID_PBM ||             st->codec->codec_id == CODEC_ID_PPM ||             st->codec->codec_id == CODEC_ID_SHORTEN ||             (st->codec->codec_id == CODEC_ID_MPEG4 && !st->need_parsing))*/)            try_decode_frame(st, pkt->data, pkt->size);        if (st->time_base.den > 0 && av_rescale_q(codec_info_duration[st->index], st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) {            break;        }        count++;    }    // close codecs which where opened in try_decode_frame()    for(i=0;i<ic->nb_streams;i++) {        st = ic->streams[i];        if(st->codec->codec)            avcodec_close(st->codec);    }    for(i=0;i<ic->nb_streams;i++) {        st = ic->streams[i];        if (st->codec->codec_type == CODEC_TYPE_VIDEO) {            if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_sample)                st->codec->codec_tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);            if(duration_count[i]               && (st->codec->time_base.num*101LL <= st->codec->time_base.den || st->codec->codec_id == CODEC_ID_MPEG2VIDEO) /*&&               //FIXME we should not special case mpeg2, but this needs testing with non mpeg2 ...               st->time_base.num*duration_sum[i]/duration_count[i]*101LL > st->time_base.den*/){                double best_error= 2*av_q2d(st->time_base);                best_error= best_error*best_error*duration_count[i]*1000*12*30;                for(j=1; j<MAX_STD_TIMEBASES; j++){                    double error= duration_error[i][j] * get_std_framerate(j);//                    if(st->codec->codec_type == CODEC_TYPE_VIDEO)//                        av_log(NULL, AV_LOG_ERROR, "%f %f\n", get_std_framerate(j) / 12.0/1001, error);                    if(error < best_error){                        best_error= error;                        av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, get_std_framerate(j), 12*1001, INT_MAX);                    }                }            }            if (!st->r_frame_rate.num){                if(    st->codec->time_base.den * (int64_t)st->time_base.num                    <= st->codec->time_base.num * (int64_t)st->time_base.den){                    st->r_frame_rate.num = st->codec->time_base.den;                    st->r_frame_rate.den = st->codec->time_base.num;                }else{                    st->r_frame_rate.num = st->time_base.den;                    st->r_frame_rate.den = st->time_base.num;                }            }        }else if(st->codec->codec_type == CODEC_TYPE_AUDIO) {            if (st->codec->codec_id == CODEC_ID_NONE && probe_data[st->index].buf_size > 0) {                codec_identified[st->index] = set_codec_from_probe_data(st, &(probe_data[st->index]), 1);                if (codec_identified[st->index]) {                    st->need_parsing = AVSTREAM_PARSE_FULL;                }            }            if(!st->codec->bits_per_sample)                st->codec->bits_per_sample= av_get_bits_per_sample(st->codec->codec_id);        }    }    av_estimate_timings(ic, old_offset);    for(i=0;i<ic->nb_streams;i++) {        st = ic->streams[i];        if (codec_identified[st->index])            break;    }    //FIXME this is a mess    if(i!=ic->nb_streams){        av_read_frame_flush(ic);        for(i=0;i<ic->nb_streams;i++) {            st = ic->streams[i];            if (codec_identified[st->index]) {                av_seek_frame(ic, st->index, 0.0, 0);            }            st->cur_dts= st->first_dts;        }        url_fseek(&ic->pb, ic->data_offset, SEEK_SET);    }#if 0    /* correct DTS for b frame streams with no timestamps */    for(i=0;i<ic->nb_streams;i++) {        st = ic->streams[i];        if (st->codec->codec_type == CODEC_TYPE_VIDEO) {            if(b-frames){                ppktl = &ic->packet_buffer;                while(ppkt1){                    if(ppkt1->stream_index != i)                        continue;                    if(ppkt1->pkt->dts < 0)                        break;                    if(ppkt1->pkt->pts != AV_NOPTS_VALUE)                        break;                    ppkt1->pkt->dts -= delta;                    ppkt1= ppkt1->next;                }                if(ppkt1)                    continue;                st->cur_dts -= delta;            }        }    }#endif    av_free(duration_error);    for(i=0;i<MAX_STREAMS;i++){        av_freep(&(probe_data[i].buf));    }    return ret;}/*******************************************************/int av_read_play(AVFormatContext *s){    if (!s->iformat->read_play)        return AVERROR(ENOSYS);    return s->iformat->read_play(s);}int av_read_pause(AVFormatContext *s){    if (!s->iformat->read_pause)        return AVERROR(ENOSYS);    return s->iformat->read_pause(s);}void av_close_input_file(AVFormatContext *s){    int i, must_open_file;    AVStream *st;    /* free previous packet */    if (s->cur_st && s->cur_st->parser)        av_free_packet(&s->cur_pkt);    if (s->iformat->read_close)        s->iformat->read_close(s);    for(i=0;i<s->nb_streams;i++) {        /* free all data in a stream component */        st = s->streams[i];        if (st->parser) {            av_parser_close(st->parser);        }        av_free(st->index_entries);        av_free(st->codec->extradata);        av_free(st->codec);        av_free

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?