📄 utils.c
字号:
(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; /* HACK/FIXME we skip all zero size audio packets so a encoder can pass pts by outputing zero size packets */ if(st->codec.codec_type==CODEC_TYPE_AUDIO && size==0) ret = 0; else ret = s->oformat->write_packet(s, stream_index, buf, size, st->pts.val & pts_mask); if (ret < 0) return ret; /* update pts */ switch (st->codec.codec_type) { case CODEC_TYPE_AUDIO: frame_size = get_audio_frame_size(&st->codec, size); /* HACK/FIXME, we skip the initial 0-size packets as they are most likely equal to the encoder delay, but it would be better if we had the real timestamps from the encoder */ if (frame_size >= 0 && (size || st->pts.num!=st->pts.den>>1 || st->pts.val)) { 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]; av_log(NULL, AV_LOG_DEBUG, "%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) { av_log(NULL, AV_LOG_DEBUG, " 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; av_log(NULL, AV_LOG_DEBUG, "%02d:%02d:%02d.%01d", hours, mins, secs, (10 * us) / AV_TIME_BASE); } else { av_log(NULL, AV_LOG_DEBUG, "N/A"); } av_log(NULL, AV_LOG_DEBUG, ", bitrate: "); if (ic->bit_rate) { av_log(NULL, AV_LOG_DEBUG,"%d kb/s", ic->bit_rate / 1000); } else { av_log(NULL, AV_LOG_DEBUG, "N/A"); } av_log(NULL, AV_LOG_DEBUG, "\n"); } for(i=0;i<ic->nb_streams;i++) { AVStream *st = ic->streams[i]; avcodec_string(buf, sizeof(buf), &st->codec, is_output); av_log(NULL, AV_LOG_DEBUG, " 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) { av_log(NULL, AV_LOG_DEBUG, "[0x%x]", st->id); } av_log(NULL, AV_LOG_DEBUG, ": %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; //FIXME use av_d2q() *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){ const char *p; int64_t t; struct tm dt; int i; static const char *date_fmt[] = { "%Y-%m-%d", "%Y%m%d", }; static const char *time_fmt[] = { "%H:%M:%S", "%H%M%S", }; const char *q; int is_utc, len; char lastch;#undef time time_t now = time(0); len = strlen(datestr); if (len > 0) lastch = datestr[len - 1]; else lastch = '\0'; is_utc = (lastch == 'z' || lastch == 'Z'); memset(&dt, 0, sizeof(dt)); p = datestr; q = NULL; if (!duration) { for (i = 0; i < sizeof(date_fmt) / sizeof(date_fmt[0]); i++) { q = small_strptime(p, date_fmt[i], &dt); if (q) { break; } } if (!q) { if (is_utc) { dt = *gmtime(&now); } else { dt = *localtime(&now); } dt.tm_hour = dt.tm_min = dt.tm_sec = 0; } else { p = q; } if (*p == 'T' || *p == 't' || *p == ' ') p++; for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) { q = small_strptime(p, time_fmt[i], &dt); if (q) { break; } } } else { q = small_strptime(p, time_fmt[0], &dt); if (!q) { dt.tm_sec = strtol(p, (char **)&q, 10); dt.tm_min = 0; dt.tm_hour = 0; } } /* Now we have all the fields that we can get */ if (!q) { if (duration) return 0; else return now * int64_t_C(1000000); } if (duration) { t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec; } else { dt.tm_isdst = -1; /* unknown */ if (is_utc) { t = mktimegm(&dt); } else { t = mktime(&dt); } } t *= 1000000; if (*q == '.') { int val, n; q++; for (val = 0, n = 100000; n >= 1; n /= 10, q++) { if (!isdigit(*q)) break; val += n * (*q - '0'); } t += val; } return t;}/* syntax: '?tag1=val1&tag2=val2...'. Little URL decoding is done. Return 1 if found */int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info){ const char *p; char tag[128], *q; p = info; if (*p == '?') p++; for(;;) { q = tag; while (*p != '\0' && *p != '=' && *p != '&') { if ((q - tag) < sizeof(tag) - 1) *q++ = *p; p++; } *q = '\0'; q = arg; if (*p == '=') { p++; while (*p != '&' && *p != '\0') { if ((q - arg) < arg_size - 1) { if (*p == '+') *q++ = ' '; else *q++ = *p; } p++; } *q = '\0'; } if (!strcmp(tag, tag1)) return 1; if (*p != '&') break; p++; } return 0;}/* Return in 'buf' the path with '%d' replaced by number. Also handles the '%0nd' format where 'n' is the total number of digits and '%%'. Return 0 if OK, and -1 if format error */int get_frame_filename(char *buf, int buf_size, const char *path, int number){ const char *p; char *q, buf1[20], c; int nd, len, percentd_found; q = buf; p = path; percentd_found = 0; for(;;) { c = *p++; if (c == '\0') break; if (c == '%') { do { nd = 0; while (isdigit(*p)) { nd = nd * 10 + *p++ - '0'; } c = *p++; } while (isdigit(c)); switch(c) { case '%': goto addchar; case 'd': if (percentd_found) goto fail; percentd_found = 1; snprintf(buf1, sizeof(buf1), "%0*d", nd, number); len = strlen(buf1); if ((q - buf + len) > buf_size - 1) goto fail; memcpy(q, buf1, len); q += len; break; default: goto fail; } } else { addchar: if ((q - buf) < buf_size - 1) *q++ = c; } } if (!percentd_found) goto fail; *q = '\0'; return 0; fail: *q = '\0'; return -1;}/** * Print nice hexa dump of a buffer * @param f stream for output * @param buf buffer * @param size buffer size */void av_hex_dump(FILE *f, uint8_t *buf, int size){ int len, i, j, c; for(i=0;i<size;i+=16) { len = size - i; if (len > 16) len = 16; fprintf(f, "%08x ", i); for(j=0;j<16;j++) { if (j < len) fprintf(f, " %02x", buf[i+j]); else fprintf(f, " "); } fprintf(f, " "); for(j=0;j<len;j++) { c = buf[i+j]; if (c < ' ' ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -