📄 utils.c
字号:
if (st->codec_info_state == CSTATE_DECODING) { /* decode the data and update codec parameters */ ptr = pkt->data; size = pkt->size; while (size > 0) { switch(st->codec.codec_type) { case CODEC_TYPE_VIDEO: ret = avcodec_decode_video(&st->codec, &picture, &got_picture, ptr, size); break; case CODEC_TYPE_AUDIO: ret = avcodec_decode_audio(&st->codec, samples, &got_picture, ptr, size); break; default: ret = -1; break; } if (ret < 0) { /* if error, simply ignore because another packet may be OK */ break; } if (got_picture) { /* we got the parameters - now we can stop examining this stream */ /* XXX: add a codec info so that we can decide if the codec can repeat frames */ if (st->codec.codec_id == CODEC_ID_MPEG1VIDEO && ic->iformat != &mpegts_demux && st->codec.sub_id == 2) { /* for mpeg2 video, we want to know the real frame rate, so we decode 40 frames. In mpeg TS case we do not do it because it would be too long */ st->codec_info_nb_real_frames++; st->codec_info_nb_repeat_frames += st->codec.coded_frame->repeat_pict;#if 0 /* XXX: testing */ if ((st->codec_info_nb_real_frames % 24) == 23) { st->codec_info_nb_repeat_frames += 2; }#endif /* stop after 40 frames */ if (st->codec_info_nb_real_frames >= 40) { av_reduce( &st->r_frame_rate, &st->r_frame_rate_base, (int64_t)st->codec.frame_rate * st->codec_info_nb_real_frames, (st->codec_info_nb_real_frames + (st->codec_info_nb_repeat_frames >> 1)) * st->codec.frame_rate_base, 1<<30); goto close_codec; } } else { close_codec: st->codec_info_state = CSTATE_FOUND; avcodec_close(&st->codec); break; } } ptr += ret; size -= ret; } } count++; } /* close each codec if there are opened */ for(i=0;i<ic->nb_streams;i++) { st = ic->streams[i]; if (st->codec_info_state == CSTATE_DECODING) avcodec_close(&st->codec); } /* set real frame rate info */ for(i=0;i<ic->nb_streams;i++) { st = ic->streams[i]; if (st->codec.codec_type == CODEC_TYPE_VIDEO) { if (!st->r_frame_rate){ st->r_frame_rate = st->codec.frame_rate; st->r_frame_rate_base = st->codec.frame_rate_base; } } } av_estimate_timings(ic); return ret;}/** * 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; 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]; av_free(st); } if (s->packet_buffer) { AVPacketList *p, *p1; p = s->packet_buffer; while (p != NULL) { p1 = p->next; av_free_packet(&p->pkt); av_free(p); p = p1; } s->packet_buffer = NULL; } 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) return NULL; st = av_mallocz(sizeof(AVStream)); if (!st) return NULL; avcodec_get_context_defaults(&st->codec); if (s->iformat) { /* no default bitrate if decoding */ st->codec.bit_rate = 0; } st->index = s->nb_streams; st->id = id; st->start_time = AV_NOPTS_VALUE; st->duration = AV_NOPTS_VALUE; s->streams[s->nb_streams++] = st; return st;}/************************************************************//* output media file */int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap){ int ret; if (s->oformat->priv_data_size > 0) { s->priv_data = av_mallocz(s->oformat->priv_data_size); if (!s->priv_data) return AVERROR_NOMEM; } else s->priv_data = NULL; if (s->oformat->set_parameters) { ret = s->oformat->set_parameters(s, ap); if (ret < 0) return ret; } return 0;}/** * allocate the stream private data and write the stream header to an * output media file * * @param s media file handle * @return 0 if OK. AVERROR_xxx if error. */int av_write_header(AVFormatContext *s){ int ret, i; AVStream *st; /* default pts settings is MPEG like */ av_set_pts_info(s, 33, 1, 90000); ret = s->oformat->write_header(s); if (ret < 0) return ret; /* init PTS generation */ for(i=0;i<s->nb_streams;i++) { st = s->streams[i]; switch (st->codec.codec_type) { case CODEC_TYPE_AUDIO: av_frac_init(&st->pts, 0, 0, (int64_t)s->pts_num * st->codec.sample_rate); break; case CODEC_TYPE_VIDEO: av_frac_init(&st->pts, 0, 0, (int64_t)s->pts_num * st->codec.frame_rate); break; default: break; } } return 0;}/** * Write a packet to an output media file. The packet shall contain * one audio or video frame. * * @param s media file handle * @param stream_index stream index * @param buf buffer containing the frame data * @param size size of buffer * @return < 0 if error, = 0 if OK, 1 if end of stream wanted. */int av_write_frame(AVFormatContext *s, int stream_index, const uint8_t *buf, int size){ AVStream *st; int64_t pts_mask; int ret, frame_size; st = s->streams[stream_index]; pts_mask = (1LL << s->pts_wrap_bits) - 1; ret = s->oformat->write_packet(s, stream_index, (uint8_t *)buf, size, st->pts.val & pts_mask); if (ret < 0) return ret; /* update pts */ switch (st->codec.codec_type) { case CODEC_TYPE_AUDIO: if (st->codec.frame_size <= 1) { frame_size = size / st->codec.channels; /* specific hack for pcm codecs because no frame size is provided */ switch(st->codec.codec_id) { case CODEC_ID_PCM_S16LE: case CODEC_ID_PCM_S16BE: case CODEC_ID_PCM_U16LE: case CODEC_ID_PCM_U16BE: frame_size >>= 1; break; default: break; } } else { frame_size = st->codec.frame_size; } av_frac_add(&st->pts, (int64_t)s->pts_den * frame_size); break; case CODEC_TYPE_VIDEO: av_frac_add(&st->pts, (int64_t)s->pts_den * st->codec.frame_rate_base); break; default: break; } return ret;}/** * write the stream trailer to an output media file and and free the * file private data. * * @param s media file handle * @return 0 if OK. AVERROR_xxx if error. */int av_write_trailer(AVFormatContext *s){ int ret; ret = s->oformat->write_trailer(s); av_freep(&s->priv_data); return ret;}/* "user interface" functions */void dump_format(AVFormatContext *ic, int index, const char *url, int is_output){ int i, flags; char buf[256]; fprintf(stderr, "%s #%d, %s, %s '%s':\n", is_output ? "Output" : "Input", index, is_output ? ic->oformat->name : ic->iformat->name, is_output ? "to" : "from", url); if (!is_output) { fprintf(stderr, " Duration: "); if (ic->duration != AV_NOPTS_VALUE) { int hours, mins, secs, us; secs = ic->duration / AV_TIME_BASE; us = ic->duration % AV_TIME_BASE; mins = secs / 60; secs %= 60; hours = mins / 60; mins %= 60; fprintf(stderr, "%02d:%02d:%02d.%01d", hours, mins, secs, (10 * us) / AV_TIME_BASE); } else { fprintf(stderr, "N/A"); } fprintf(stderr, ", bitrate: "); if (ic->bit_rate) { fprintf(stderr,"%d kb/s", ic->bit_rate / 1000); } else { fprintf(stderr, "N/A"); } fprintf(stderr, "\n"); } for(i=0;i<ic->nb_streams;i++) { AVStream *st = ic->streams[i]; avcodec_string(buf, sizeof(buf), &st->codec, is_output); fprintf(stderr, " Stream #%d.%d", index, i); /* the pid is an important information, so we display it */ /* XXX: add a generic system */ if (is_output) flags = ic->oformat->flags; else flags = ic->iformat->flags; if (flags & AVFMT_SHOW_IDS) { fprintf(stderr, "[0x%x]", st->id); } fprintf(stderr, ": %s\n", buf); }}typedef struct { const char *abv; int width, height; int frame_rate, frame_rate_base;} AbvEntry;static AbvEntry frame_abvs[] = { { "ntsc", 720, 480, 30000, 1001 }, { "pal", 720, 576, 25, 1 }, { "qntsc", 352, 240, 30000, 1001 }, /* VCD compliant ntsc */ { "qpal", 352, 288, 25, 1 }, /* VCD compliant pal */ { "sntsc", 640, 480, 30000, 1001 }, /* square pixel ntsc */ { "spal", 768, 576, 25, 1 }, /* square pixel pal */ { "film", 352, 240, 24, 1 }, { "ntsc-film", 352, 240, 24000, 1001 }, { "sqcif", 128, 96, 0, 0 }, { "qcif", 176, 144, 0, 0 }, { "cif", 352, 288, 0, 0 }, { "4cif", 704, 576, 0, 0 },};int parse_image_size(int *width_ptr, int *height_ptr, const char *str){ int i; int n = sizeof(frame_abvs) / sizeof(AbvEntry); const char *p; int frame_width = 0, frame_height = 0; for(i=0;i<n;i++) { if (!strcmp(frame_abvs[i].abv, str)) { frame_width = frame_abvs[i].width; frame_height = frame_abvs[i].height; break; } } if (i == n) { p = str; frame_width = strtol(p, (char **)&p, 10); if (*p) p++; frame_height = strtol(p, (char **)&p, 10); } if (frame_width <= 0 || frame_height <= 0) return -1; *width_ptr = frame_width; *height_ptr = frame_height; return 0;}int parse_frame_rate(int *frame_rate, int *frame_rate_base, const char *arg){ int i; char* cp; /* First, we check our abbreviation table */ for (i = 0; i < sizeof(frame_abvs)/sizeof(*frame_abvs); ++i) if (!strcmp(frame_abvs[i].abv, arg)) { *frame_rate = frame_abvs[i].frame_rate; *frame_rate_base = frame_abvs[i].frame_rate_base; return 0; } /* Then, we try to parse it as fraction */ cp = strchr(arg, '/'); if (cp) { char* cpp; *frame_rate = strtol(arg, &cpp, 10); if (cpp != arg || cpp == cp) *frame_rate_base = strtol(cp+1, &cpp, 10); else *frame_rate = 0; } else { /* Finally we give up and parse it as double */ *frame_rate_base = DEFAULT_FRAME_RATE_BASE; *frame_rate = (int)(strtod(arg, 0) * (*frame_rate_base) + 0.5); } if (!*frame_rate || !*frame_rate_base) return -1; else return 0;}/* Syntax: * - If not a duration: * [{YYYY-MM-DD|YYYYMMDD}]{T| }{HH[:MM[:SS[.m...]]][Z]|HH[MM[SS[.m...]]][Z]} * Time is localtime unless Z is suffixed to the end. In this case GMT * Return the date in micro seconds since 1970 * - If duration: * HH[:MM[:SS[.m...]]] * S+[.m...] */int64_t parse_date(const char *datestr, int duration)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -