utils.c
来自「pmpmodavc102_sub_src,psp下很好的播放器源码」· C语言 代码 · 共 2,173 行 · 第 1/5 页
C
2,173 行
} ic->file_size = file_size; if ((ic->iformat == &mpegps_demux || ic->iformat == &mpegts_demux) && file_size && !ic->pb.is_streamed) { /* get accurate estimate from the PTSes */ av_estimate_timings_from_pts(ic); } else if (av_has_timings(ic)) { /* at least one components has timings - we use them for all the components */ fill_all_stream_timings(ic); } else { /* less precise: use bit rate info */ av_estimate_timings_from_bit_rate(ic); } av_update_stream_timings(ic);#if 0 { int i; AVStream *st; for(i = 0;i < ic->nb_streams; i++) { st = ic->streams[i]; printf("%d: start_time: %0.3f duration: %0.3f\n", i, (double)st->start_time / AV_TIME_BASE, (double)st->duration / AV_TIME_BASE); } printf("stream: start_time: %0.3f duration: %0.3f bitrate=%d kb/s\n", (double)ic->start_time / AV_TIME_BASE, (double)ic->duration / AV_TIME_BASE, ic->bit_rate / 1000); }#endif}static int has_codec_parameters(AVCodecContext *enc){ int val; switch(enc->codec_type) { case CODEC_TYPE_AUDIO: val = enc->sample_rate; break; case CODEC_TYPE_VIDEO: val = enc->width && enc->pix_fmt != PIX_FMT_NONE; break; default: val = 1; break; } return (val != 0);}static int try_decode_frame(AVStream *st, const uint8_t *data, int size){ int16_t *samples; AVCodec *codec; int got_picture, ret=0; AVFrame picture; if(!st->codec->codec){ codec = avcodec_find_decoder(st->codec->codec_id); if (!codec) return -1; ret = avcodec_open(st->codec, codec); 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: samples = av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); if (!samples) goto fail; ret = avcodec_decode_audio(st->codec, samples, &got_picture, (uint8_t *)data, size); av_free(samples); break; default: break; } } fail: return ret;}/* absolute maximum size we read until we abort */#define MAX_READ_SIZE 5000000/* maximum duration until we stop analysing the stream */#define MAX_STREAM_DURATION ((int)(AV_TIME_BASE * 2.0))/** * Read the beginning of a media file to get stream information. This * is useful for file formats with no headers such as MPEG. This * function also compute the real frame rate in case of mpeg2 repeat * frame mode. * * @param ic media file handle * @return >=0 if OK. AVERROR_xxx if error. * @todo let user decide somehow what information is needed so we dont waste time geting stuff the user doesnt need */int av_find_stream_info(AVFormatContext *ic){ int i, count, ret, read_size; AVStream *st; AVPacket pkt1, *pkt; AVPacketList *pktl=NULL, **ppktl; int64_t last_dts[MAX_STREAMS]; int64_t duration_sum[MAX_STREAMS]; int duration_count[MAX_STREAMS]={0}; 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 == 2 && st->parser){ st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; } } } for(i=0;i<MAX_STREAMS;i++){ last_dts[i]= AV_NOPTS_VALUE; duration_sum[i]= INT64_MAX; } count = 0; read_size = 0; ppktl = &ic->packet_buffer; 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 >= 1000LL*st->codec->time_base.num && duration_count[i]<20 && st->codec->codec_type == CODEC_TYPE_VIDEO) break; if(st->parser && st->parser->parser->split && !st->codec->extradata) 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; } } else { /* 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)) break; } if (i == ic->nb_streams) ret = 0; break; } pktl = av_mallocz(sizeof(AVPacketList)); if (!pktl) { ret = AVERROR_NOMEM; break; } /* add the packet in the buffered packet list */ *ppktl = pktl; ppktl = &pktl->next; pkt = &pktl->pkt; *pkt = pkt1; /* duplicate the packet */ if (av_dup_packet(pkt) < 0) { ret = AVERROR_NOMEM; break; } read_size += pkt->size; st = ic->streams[pkt->stream_index]; st->codec_info_duration += pkt->duration; if (pkt->duration != 0) st->codec_info_nb_frames++; { 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){ if(duration*duration_count[index]*10/9 < duration_sum[index]){ duration_sum[index]= duration; duration_count[index]=1; }else{ int factor= av_rescale(duration, duration_count[index], duration_sum[index]); duration_sum[index] += duration; duration_count[index]+= factor; } if(st->codec_info_nb_frames == 0 && 0) st->codec_info_duration += duration; } last_dts[pkt->stream_index]= pkt->dts; } 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); memcpy(st->codec->extradata, pkt->data, st->codec->extradata_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 (av_rescale_q(st->codec_info_duration, st->time_base, AV_TIME_BASE_Q) >= MAX_STREAM_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*1000LL <= st->codec->time_base.den && st->time_base.num*duration_sum[i]/duration_count[i]*1000LL > st->time_base.den){ AVRational fps1; int64_t num, den; num= st->time_base.den*duration_count[i]; den= st->time_base.num*duration_sum[i]; av_reduce(&fps1.num, &fps1.den, num*1001, den*1000, FFMAX(st->time_base.den, st->time_base.num)/4); av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, den, FFMAX(st->time_base.den, st->time_base.num)/4); if(fps1.num < st->r_frame_rate.num && fps1.den == 1 && (fps1.num==24 || fps1.num==30)){ //FIXME better decission st->r_frame_rate.num= fps1.num*1000; st->r_frame_rate.den= fps1.den*1001; } } /* set real frame rate info */ /* compute the real frame rate for telecine */ if ((st->codec->codec_id == CODEC_ID_MPEG1VIDEO || st->codec->codec_id == CODEC_ID_MPEG2VIDEO) && st->codec->sub_id == 2) { if (st->codec_info_nb_frames >= 20) { float coded_frame_rate, est_frame_rate; est_frame_rate = ((double)st->codec_info_nb_frames * AV_TIME_BASE) / (double)st->codec_info_duration ; coded_frame_rate = 1.0/av_q2d(st->codec->time_base);#if 0 printf("telecine: coded_frame_rate=%0.3f est_frame_rate=%0.3f\n", coded_frame_rate, est_frame_rate);#endif /* if we detect that it could be a telecine, we signal it. It would be better to do it at a higher level as it can change in a film */ if (coded_frame_rate >= 24.97 && (est_frame_rate >= 23.5 && est_frame_rate < 24.5)) { st->r_frame_rate = (AVRational){24000, 1001}; } } } /* if no real frame rate, use the codec one */ if (!st->r_frame_rate.num){ st->r_frame_rate.num = st->codec->time_base.den; st->r_frame_rate.den = st->codec->time_base.num; } } } av_estimate_timings(ic);#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 return ret;}/*******************************************************//** * start playing a network based stream (e.g. RTSP stream) at the * current position */int av_read_play(AVFormatContext *s){ if (!s->iformat->read_play) return AVERROR_NOTSUPP; return s->iformat->read_play(s);}/** * Pause a network based stream (e.g. RTSP stream). * * Use av_read_play() to resume it. */int av_read_pause(AVFormatContext *s){ if (!s->iformat->read_pause) return AVERROR_NOTSUPP; return s->iformat->read_pause(s);}/** * Close a media file (but not its codecs). * * @param s media file handle */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); av_free(st); } flush_packet_queue(s); must_open_file = 1; if (s->iformat->flags & AVFMT_NOFILE) { must_open_file = 0; } if (must_open_file) { url_fclose(&s->pb); } av_freep(&s->priv_data); av_free(s);}/** * Add a new stream to a media file. * * Can only be called in the read_header() function. If the flag * AVFMTCTX_NOHEADER is in the format context, then new streams * can be added in read_packet too. * * @param s media file handle * @param id file format dependent stream id */AVStream *av_new_stream(AVFormatContext *s, int id){ AVStream *st; if (s->nb_streams >= MAX_STREAMS)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?