Newer
Older
Fabrice Bellard
committed
int av_write_trailer(AVFormatContext *s)
{
int ret, i;
Michael Niedermayer
committed
for(;;){
AVPacket pkt;
ret= av_interleave_packet(s, &pkt, NULL, 1);
if(ret<0) //FIXME cleanup needed for ret<0 ?
goto fail;
Michael Niedermayer
committed
if(!ret)
break;
Michael Niedermayer
committed
ret= s->oformat->write_packet(s, &pkt);
Michael Niedermayer
committed
av_free_packet(&pkt);
goto fail;
if(url_ferror(s->pb))
if(s->oformat->write_trailer)
ret = s->oformat->write_trailer(s);
ret=url_ferror(s->pb);
av_freep(&s->streams[i]->priv_data);
av_freep(&s->streams[i]->index_entries);
}
Fabrice Bellard
committed
av_freep(&s->priv_data);
return ret;
void ff_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx)
{
int i, j;
AVProgram *program=NULL;
void *tmp;
if (idx >= ac->nb_streams) {
av_log(ac, AV_LOG_ERROR, "stream index %d is not valid\n", idx);
return;
}
for(i=0; i<ac->nb_programs; i++){
if(ac->programs[i]->id != progid)
continue;
program = ac->programs[i];
for(j=0; j<program->nb_stream_indexes; j++)
if(program->stream_index[j] == idx)
return;
tmp = av_realloc(program->stream_index, sizeof(unsigned int)*(program->nb_stream_indexes+1));
if(!tmp)
return;
program->stream_index = tmp;
program->stream_index[program->nb_stream_indexes++] = idx;
return;
}
}
static void print_fps(double d, const char *postfix){
uint64_t v= lrintf(d*100);
if (v% 100 ) av_log(NULL, AV_LOG_INFO, ", %3.2f %s", d, postfix);
else if(v%(100*1000)) av_log(NULL, AV_LOG_INFO, ", %1.0f %s", d, postfix);
else av_log(NULL, AV_LOG_INFO, ", %1.0fk %s", d/1000, postfix);
}
static void dump_metadata(void *ctx, AVMetadata *m, const char *indent)
{
Michael Niedermayer
committed
if(m && !(m->count == 1 && av_metadata_get(m, "language", NULL, 0))){
AVMetadataTag *tag=NULL;
av_log(ctx, AV_LOG_INFO, "%sMetadata:\n", indent);
while((tag=av_metadata_get(m, "", tag, AV_METADATA_IGNORE_SUFFIX))) {
av_log(ctx, AV_LOG_INFO, "%s %-16s: %s\n", indent, tag->key, tag->value);
Baptiste Coudurier
committed
static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
Nico Sabbi
committed
{
Baptiste Coudurier
committed
char buf[256];
Nico Sabbi
committed
int flags = (is_output ? ic->oformat->flags : ic->iformat->flags);
AVStream *st = ic->streams[i];
int g = av_gcd(st->time_base.num, st->time_base.den);
AVMetadataTag *lang = av_metadata_get(st->metadata, "language", NULL, 0);
Nico Sabbi
committed
avcodec_string(buf, sizeof(buf), st->codec, is_output);
av_log(NULL, AV_LOG_INFO, " Stream #%d.%d", index, i);
/* the pid is an important information, so we display it */
/* XXX: add a generic system */
if (flags & AVFMT_SHOW_IDS)
av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id);
if (lang)
av_log(NULL, AV_LOG_INFO, "(%s)", lang->value);
av_log(NULL, AV_LOG_DEBUG, ", %d, %d/%d", st->codec_info_nb_frames, st->time_base.num/g, st->time_base.den/g);
Nico Sabbi
committed
av_log(NULL, AV_LOG_INFO, ": %s", buf);
if (st->sample_aspect_ratio.num && // default
av_cmp_q(st->sample_aspect_ratio, st->codec->sample_aspect_ratio)) {
AVRational display_aspect_ratio;
av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
st->codec->width*st->sample_aspect_ratio.num,
st->codec->height*st->sample_aspect_ratio.den,
1024*1024);
av_log(NULL, AV_LOG_INFO, ", PAR %d:%d DAR %d:%d",
st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
display_aspect_ratio.num, display_aspect_ratio.den);
}
if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
if(st->avg_frame_rate.den && st->avg_frame_rate.num)
print_fps(av_q2d(st->avg_frame_rate), "fps");
Nico Sabbi
committed
if(st->r_frame_rate.den && st->r_frame_rate.num)
print_fps(av_q2d(st->r_frame_rate), "tbr");
if(st->time_base.den && st->time_base.num)
print_fps(1/av_q2d(st->time_base), "tbn");
if(st->codec->time_base.den && st->codec->time_base.num)
print_fps(1/av_q2d(st->codec->time_base), "tbc");
Nico Sabbi
committed
}
av_log(NULL, AV_LOG_INFO, "\n");
dump_metadata(NULL, st->metadata, " ");
Nico Sabbi
committed
}
uint8_t *printed = av_mallocz(ic->nb_streams);
if (ic->nb_streams && !printed)
return;
av_log(NULL, AV_LOG_INFO, "%s #%d, %s, %s '%s':\n",
index,
is_output ? ic->oformat->name : ic->iformat->name,
dump_metadata(NULL, ic->metadata, " ");
Fabrice Bellard
committed
if (!is_output) {
av_log(NULL, AV_LOG_INFO, " Duration: ");
Fabrice Bellard
committed
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_INFO, "%02d:%02d:%02d.%02d", hours, mins, secs,
(100 * us) / AV_TIME_BASE);
Fabrice Bellard
committed
} else {
av_log(NULL, AV_LOG_INFO, "N/A");
Fabrice Bellard
committed
}
Wolfram Gloger
committed
if (ic->start_time != AV_NOPTS_VALUE) {
int secs, us;
av_log(NULL, AV_LOG_INFO, ", start: ");
Wolfram Gloger
committed
secs = ic->start_time / AV_TIME_BASE;
us = abs(ic->start_time % AV_TIME_BASE);
av_log(NULL, AV_LOG_INFO, "%d.%06d",
Wolfram Gloger
committed
secs, (int)av_rescale(us, 1000000, AV_TIME_BASE));
}
av_log(NULL, AV_LOG_INFO, ", bitrate: ");
Fabrice Bellard
committed
if (ic->bit_rate) {
av_log(NULL, AV_LOG_INFO,"%d kb/s", ic->bit_rate / 1000);
Fabrice Bellard
committed
} else {
av_log(NULL, AV_LOG_INFO, "N/A");
Fabrice Bellard
committed
}
av_log(NULL, AV_LOG_INFO, "\n");
Fabrice Bellard
committed
}
for (i = 0; i < ic->nb_chapters; i++) {
AVChapter *ch = ic->chapters[i];
av_log(NULL, AV_LOG_INFO, " Chapter #%d.%d: ", index, i);
av_log(NULL, AV_LOG_INFO, "start %f, ", ch->start * av_q2d(ch->time_base));
av_log(NULL, AV_LOG_INFO, "end %f\n", ch->end * av_q2d(ch->time_base));
dump_metadata(NULL, ch->metadata, " ");
}
if(ic->nb_programs) {
int j, k, total = 0;
for(j=0; j<ic->nb_programs; j++) {
AVMetadataTag *name = av_metadata_get(ic->programs[j]->metadata,
"name", NULL, 0);
av_log(NULL, AV_LOG_INFO, " Program %d %s\n", ic->programs[j]->id,
name ? name->value : "");
dump_metadata(NULL, ic->programs[j]->metadata, " ");
for(k=0; k<ic->programs[j]->nb_stream_indexes; k++) {
Baptiste Coudurier
committed
dump_stream_format(ic, ic->programs[j]->stream_index[k], index, is_output);
printed[ic->programs[j]->stream_index[k]] = 1;
}
total += ic->programs[j]->nb_stream_indexes;
}
if (total < ic->nb_streams)
av_log(NULL, AV_LOG_INFO, " No Program\n");
}
for(i=0;i<ic->nb_streams;i++)
if (!printed[i])
dump_stream_format(ic, i, index, is_output);
av_free(printed);
#if FF_API_PARSE_FRAME_PARAM
#include "libavcore/parseutils.h"
int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
{
return av_parse_video_size(width_ptr, height_ptr, str);
Stefano Sabatini
committed
int parse_frame_rate(int *frame_rate_num, int *frame_rate_den, const char *arg)
Stefano Sabatini
committed
AVRational frame_rate;
int ret = av_parse_video_rate(&frame_rate, arg);
Stefano Sabatini
committed
*frame_rate_num= frame_rate.num;
*frame_rate_den= frame_rate.den;
return ret;
#endif
int64_t av_gettime(void)
{
struct timeval tv;
gettimeofday(&tv,NULL);
return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
}
Martin Storsjö
committed
uint64_t ff_ntp_time(void)
{
return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US;
}
int64_t parse_date(const char *datestr, int duration)
Philip Gladstone
committed
struct tm dt;
Philip Gladstone
committed
int i;
static const char * const date_fmt[] = {
Philip Gladstone
committed
"%Y-%m-%d",
"%Y%m%d",
};
static const char * const time_fmt[] = {
Philip Gladstone
committed
"%H:%M:%S",
"%H%M%S",
};
const char *q;
Philip Gladstone
committed
char lastch;
#undef time
Philip Gladstone
committed
time_t now = time(0);
len = strlen(datestr);
if (len > 0)
lastch = datestr[len - 1];
else
lastch = '\0';
Philip Gladstone
committed
is_utc = (lastch == 'z' || lastch == 'Z');
Philip Gladstone
committed
memset(&dt, 0, sizeof(dt));
Francesco Cosoleto
committed
if (!strncasecmp(datestr, "now", len))
return (int64_t) now * 1000000;
/* parse the year-month-day part */
for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) {
Fabrice Bellard
committed
q = small_strptime(p, date_fmt[i], &dt);
Philip Gladstone
committed
if (q) {
break;
}
}
/* if the year-month-day part is missing, then take the
* current year-month-day time */
Philip Gladstone
committed
if (!q) {
if (is_utc) {
dt = *gmtime(&now);
} else {
dt = *localtime(&now);
}
dt.tm_hour = dt.tm_min = dt.tm_sec = 0;
Philip Gladstone
committed
p = q;
Philip Gladstone
committed
if (*p == 'T' || *p == 't' || *p == ' ')
p++;
/* parse the hour-minute-second part */
for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) {
Fabrice Bellard
committed
q = small_strptime(p, time_fmt[i], &dt);
if (q) {
break;
}
}
} else {
/* parse datestr as a duration */
if (p[0] == '-') {
negative = 1;
++p;
}
/* parse datestr as HH:MM:SS */
Fabrice Bellard
committed
q = small_strptime(p, time_fmt[0], &dt);
/* parse datestr as S+ */
if (q == p)
/* the parsing didn't succeed */
return INT64_MIN;
Philip Gladstone
committed
}
}
/* Now we have all the fields that we can get */
if (!q) {
return INT64_MIN;
Philip Gladstone
committed
if (duration) {
Philip Gladstone
committed
t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
Philip Gladstone
committed
} else {
Philip Gladstone
committed
dt.tm_isdst = -1; /* unknown */
if (is_utc) {
t = mktimegm(&dt);
} else {
t = mktime(&dt);
}
Philip Gladstone
committed
Philip Gladstone
committed
t *= 1000000;
/* parse the .m... part */
Philip Gladstone
committed
if (*q == '.') {
Philip Gladstone
committed
q++;
for (val = 0, n = 100000; n >= 1; n /= 10, q++) {
Philip Gladstone
committed
break;
val += n * (*q - '0');
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
}
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') {
Philip Gladstone
committed
if ((q - arg) < arg_size - 1) {
if (*p == '+')
*q++ = ' ';
else
*q++ = *p;
}
*q = '\0';
Michel Bardiaux
committed
int av_get_frame_filename(char *buf, int buf_size,
const char *path, int number)
Panagiotis Issaris
committed
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 == '%') {
Philip Gladstone
committed
do {
nd = 0;
while (isdigit(*p)) {
nd = nd * 10 + *p++ - '0';
}
c = *p++;
} while (isdigit(c));
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
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;
}
Panagiotis Issaris
committed
static void hex_dump_internal(void *avcl, FILE *f, int level, uint8_t *buf, int size)
Fabrice Bellard
committed
{
int len, i, j, c;
#undef fprintf
Panagiotis Issaris
committed
#define PRINT(...) do { if (!f) av_log(avcl, level, __VA_ARGS__); else fprintf(f, __VA_ARGS__); } while(0)
Fabrice Bellard
committed
for(i=0;i<size;i+=16) {
len = size - i;
if (len > 16)
len = 16;
Panagiotis Issaris
committed
PRINT("%08x ", i);
Fabrice Bellard
committed
for(j=0;j<16;j++) {
if (j < len)
Panagiotis Issaris
committed
PRINT(" %02x", buf[i+j]);
Fabrice Bellard
committed
else
Panagiotis Issaris
committed
PRINT(" ");
Fabrice Bellard
committed
}
Panagiotis Issaris
committed
PRINT(" ");
Fabrice Bellard
committed
for(j=0;j<len;j++) {
c = buf[i+j];
if (c < ' ' || c > '~')
c = '.';
Panagiotis Issaris
committed
PRINT("%c", c);
Fabrice Bellard
committed
}
Panagiotis Issaris
committed
PRINT("\n");
Fabrice Bellard
committed
}
Panagiotis Issaris
committed
#undef PRINT
}
void av_hex_dump(FILE *f, uint8_t *buf, int size)
{
hex_dump_internal(NULL, f, 0, buf, size);
}
void av_hex_dump_log(void *avcl, int level, uint8_t *buf, int size)
{
hex_dump_internal(avcl, NULL, level, buf, size);
Fabrice Bellard
committed
}
Panagiotis Issaris
committed
static void pkt_dump_internal(void *avcl, FILE *f, int level, AVPacket *pkt, int dump_payload)
#undef fprintf
Panagiotis Issaris
committed
#define PRINT(...) do { if (!f) av_log(avcl, level, __VA_ARGS__); else fprintf(f, __VA_ARGS__); } while(0)
PRINT("stream #%d:\n", pkt->stream_index);
PRINT(" keyframe=%d\n", ((pkt->flags & AV_PKT_FLAG_KEY) != 0));
Panagiotis Issaris
committed
PRINT(" duration=%0.3f\n", (double)pkt->duration / AV_TIME_BASE);
/* DTS is _always_ valid after av_read_frame() */
Panagiotis Issaris
committed
PRINT(" dts=");
if (pkt->dts == AV_NOPTS_VALUE)
Panagiotis Issaris
committed
PRINT("N/A");
Panagiotis Issaris
committed
PRINT("%0.3f", (double)pkt->dts / AV_TIME_BASE);
/* PTS may not be known if B-frames are present. */
Panagiotis Issaris
committed
PRINT(" pts=");
if (pkt->pts == AV_NOPTS_VALUE)
Panagiotis Issaris
committed
PRINT("N/A");
Panagiotis Issaris
committed
PRINT("%0.3f", (double)pkt->pts / AV_TIME_BASE);
PRINT("\n");
PRINT(" size=%d\n", pkt->size);
#undef PRINT
if (dump_payload)
av_hex_dump(f, pkt->data, pkt->size);
}
Panagiotis Issaris
committed
void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload)
{
pkt_dump_internal(NULL, f, 0, pkt, dump_payload);
}
void av_pkt_dump_log(void *avcl, int level, AVPacket *pkt, int dump_payload)
{
pkt_dump_internal(avcl, NULL, level, pkt, dump_payload);
}
Aurelien Jacobs
committed
#if FF_API_URL_SPLIT
void ff_url_split(char *proto, int proto_size,
char *authorization, int authorization_size,
char *hostname, int hostname_size,
int *port_ptr,
char *path, int path_size,
const char *url)
{
av_url_split(proto, proto_size,
authorization, authorization_size,
hostname, hostname_size,
port_ptr,
path, path_size,
url);
}
#endif
void av_url_split(char *proto, int proto_size,
char *authorization, int authorization_size,
char *hostname, int hostname_size,
int *port_ptr,
char *path, int path_size,
const char *url)
Michael Niedermayer
committed
const char *p, *ls, *at, *col, *brk;
if (port_ptr) *port_ptr = -1;
if (proto_size > 0) proto[0] = 0;
if (authorization_size > 0) authorization[0] = 0;
if (hostname_size > 0) hostname[0] = 0;
if (path_size > 0) path[0] = 0;
/* parse protocol */
if ((p = strchr(url, ':'))) {
av_strlcpy(proto, url, FFMIN(proto_size, p + 1 - url));
p++; /* skip ':' */
if (*p == '/') p++;
if (*p == '/') p++;
/* no protocol means plain filename */
av_strlcpy(path, url, path_size);
return;
}
Petr Doubek
committed
/* separate path from hostname */
Michael Niedermayer
committed
ls = strchr(p, '/');
if(!ls)
ls = strchr(p, '?');
if(ls)
Michael Niedermayer
committed
else
ls = &p[strlen(p)]; // XXX
/* the rest is hostname, use that to parse auth/port */
if (ls != p) {
/* authorization (user[:pass]@hostname) */
if ((at = strchr(p, '@')) && at < ls) {
av_strlcpy(authorization, p,
FFMIN(authorization_size, at + 1 - p));
p = at + 1; /* skip '@' */
if (*p == '[' && (brk = strchr(p, ']')) && brk < ls) {
/* [host]:port */
av_strlcpy(hostname, p + 1,
FFMIN(hostname_size, brk - p));
if (brk[1] == ':' && port_ptr)
*port_ptr = atoi(brk + 2);
} else if ((col = strchr(p, ':')) && col < ls) {
av_strlcpy(hostname, p,
FFMIN(col + 1 - p, hostname_size));
if (port_ptr) *port_ptr = atoi(col + 1);
} else
av_strlcpy(hostname, p,
FFMIN(ls + 1 - p, hostname_size));
char *ff_data_to_hex(char *buff, const uint8_t *src, int s, int lowercase)
Ronald S. Bultje
committed
{
int i;
static const char hex_table_uc[16] = { '0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'A', 'B',
'C', 'D', 'E', 'F' };
static const char hex_table_lc[16] = { '0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f' };
const char *hex_table = lowercase ? hex_table_lc : hex_table_uc;
Ronald S. Bultje
committed
for(i = 0; i < s; i++) {
Ronald S. Bultje
committed
buff[i * 2] = hex_table[src[i] >> 4];
buff[i * 2 + 1] = hex_table[src[i] & 0xF];
Ronald S. Bultje
committed
}
return buff;
}
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
int ff_hex_to_data(uint8_t *data, const char *p)
{
int c, len, v;
len = 0;
v = 1;
for (;;) {
p += strspn(p, SPACE_CHARS);
if (*p == '\0')
break;
c = toupper((unsigned char) *p++);
if (c >= '0' && c <= '9')
c = c - '0';
else if (c >= 'A' && c <= 'F')
c = c - 'A' + 10;
else
break;
v = (v << 4) | c;
if (v & 0x100) {
if (data)
data[len] = v;
len++;
v = 1;
}
}
return len;
}
void av_set_pts_info(AVStream *s, int pts_wrap_bits,
unsigned int pts_num, unsigned int pts_den)
if(av_reduce(&s->time_base.num, &s->time_base.den, pts_num, pts_den, INT_MAX)){
if(s->time_base.num != pts_num)
av_log(NULL, AV_LOG_DEBUG, "st:%d removing common factor %d from timebase\n", s->index, pts_num/s->time_base.num);
}else
av_log(NULL, AV_LOG_WARNING, "st:%d has too large timebase, reducing\n", s->index);
if(!s->time_base.num || !s->time_base.den)
s->time_base.num= s->time_base.den= 0;
int ff_url_join(char *str, int size, const char *proto,
const char *authorization, const char *hostname,
int port, const char *fmt, ...)
{
#if CONFIG_NETWORK
struct addrinfo hints, *ai;
#endif
str[0] = '\0';
if (proto)
av_strlcatf(str, size, "%s://", proto);
if (authorization && authorization[0])
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
av_strlcatf(str, size, "%s@", authorization);
#if CONFIG_NETWORK && defined(AF_INET6)
/* Determine if hostname is a numerical IPv6 address,
* properly escape it within [] in that case. */
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_NUMERICHOST;
if (!getaddrinfo(hostname, NULL, &hints, &ai)) {
if (ai->ai_family == AF_INET6) {
av_strlcat(str, "[", size);
av_strlcat(str, hostname, size);
av_strlcat(str, "]", size);
} else {
av_strlcat(str, hostname, size);
}
freeaddrinfo(ai);
} else
#endif
/* Not an IPv6 address, just output the plain string. */
av_strlcat(str, hostname, size);
if (port >= 0)
av_strlcatf(str, size, ":%d", port);
if (fmt) {
va_list vl;
int len = strlen(str);
va_start(vl, fmt);
vsnprintf(str + len, size > len ? size - len : 0, fmt, vl);
va_end(vl);
}
return strlen(str);
}
int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt,
AVFormatContext *src)
{
AVPacket local_pkt;
local_pkt = *pkt;
local_pkt.stream_index = dst_stream;
if (pkt->pts != AV_NOPTS_VALUE)
local_pkt.pts = av_rescale_q(pkt->pts,
src->streams[pkt->stream_index]->time_base,
dst->streams[dst_stream]->time_base);
if (pkt->dts != AV_NOPTS_VALUE)
local_pkt.dts = av_rescale_q(pkt->dts,
src->streams[pkt->stream_index]->time_base,
dst->streams[dst_stream]->time_base);
return av_write_frame(dst, &local_pkt);
}
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf,
void *context)
{
const char *ptr = str;
/* Parse key=value pairs. */
for (;;) {
const char *key;
char *dest = NULL, *dest_end;
int key_len, dest_len = 0;
/* Skip whitespace and potential commas. */
while (*ptr && (isspace(*ptr) || *ptr == ','))
ptr++;
if (!*ptr)
break;
key = ptr;
if (!(ptr = strchr(key, '=')))
break;
ptr++;
key_len = ptr - key;
callback_get_buf(context, key, key_len, &dest, &dest_len);
dest_end = dest + dest_len - 1;
if (*ptr == '\"') {
ptr++;
while (*ptr && *ptr != '\"') {
if (*ptr == '\\') {
if (!ptr[1])
break;
if (dest && dest < dest_end)
*dest++ = ptr[1];
ptr += 2;
} else {
if (dest && dest < dest_end)
*dest++ = *ptr;
ptr++;
}
}
if (*ptr == '\"')
ptr++;
} else {
for (; *ptr && !(isspace(*ptr) || *ptr == ','); ptr++)
if (dest && dest < dest_end)
*dest++ = *ptr;
}
if (dest)
*dest = 0;
}
}