Newer
Older
goto fail;
}
frac_init(&st->pts, 0, 0, den);
Wolfram Gloger
committed
}
if (options) {
av_dict_free(options);
*options = tmp;
}
fail:
av_dict_free(&tmp);
return ret;
Fabrice Bellard
committed
}
//FIXME merge with compute_pkt_fields
Baptiste Coudurier
committed
static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt){
int delay = FFMAX(st->codec->has_b_frames, !!st->codec->max_b_frames);
int num, den, frame_size, i;
av_dlog(s, "compute_pkt_fields2: pts:%"PRId64" dts:%"PRId64" cur_dts:%"PRId64" b:%d size:%d st:%d\n",
pkt->pts, pkt->dts, st->cur_dts, delay, pkt->size, pkt->stream_index);
/* if(pkt->pts == AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE)
return AVERROR(EINVAL);*/
if (pkt->duration == 0) {
compute_frame_duration(&num, &den, st, NULL, pkt);
if (den && num) {
pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den * st->codec->ticks_per_frame, den * (int64_t)st->time_base.num);
Michael Niedermayer
committed
if(pkt->pts == AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && delay==0)
pkt->pts= pkt->dts;
//XXX/FIXME this is a temporary hack until all encoders output pts
if((pkt->pts == 0 || pkt->pts == AV_NOPTS_VALUE) && pkt->dts == AV_NOPTS_VALUE && !delay){
pkt->dts=
// pkt->pts= st->cur_dts;
pkt->pts= st->pts.val;
}
Baptiste Coudurier
committed
if(pkt->pts != AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY){
st->pts_buffer[0]= pkt->pts;
for(i=1; i<delay+1 && st->pts_buffer[i] == AV_NOPTS_VALUE; i++)
st->pts_buffer[i]= pkt->pts + (i-delay-1) * pkt->duration;
for(i=0; i<delay && st->pts_buffer[i] > st->pts_buffer[i+1]; i++)
FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i+1]);
pkt->dts= st->pts_buffer[0];
Michael Niedermayer
committed
if(st->cur_dts && st->cur_dts != AV_NOPTS_VALUE && st->cur_dts >= pkt->dts){
Baptiste Coudurier
committed
av_log(s, AV_LOG_ERROR,
"Application provided invalid, non monotonically increasing dts to muxer in stream %d: %"PRId64" >= %"PRId64"\n",
Baptiste Coudurier
committed
st->index, st->cur_dts, pkt->dts);
return AVERROR(EINVAL);
Michael Niedermayer
committed
}
if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts < pkt->dts){
av_log(s, AV_LOG_ERROR, "pts < dts in stream %d\n", st->index);
return AVERROR(EINVAL);
Michael Niedermayer
committed
}
Baptiste Coudurier
committed
// av_log(s, AV_LOG_DEBUG, "av_write_frame: pts2:%"PRId64" dts2:%"PRId64"\n", pkt->pts, pkt->dts);
st->cur_dts= pkt->dts;
st->pts.val= pkt->dts;
Michael Niedermayer
committed
switch (st->codec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
Michael Niedermayer
committed
frame_size = get_audio_frame_size(st->codec, pkt->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 && (pkt->size || st->pts.num!=st->pts.den>>1 || st->pts.val)) {
frac_add(&st->pts, (int64_t)st->time_base.den * frame_size);
Fabrice Bellard
committed
}
case AVMEDIA_TYPE_VIDEO:
frac_add(&st->pts, (int64_t)st->time_base.den * st->codec->time_base.num);
break;
default:
break;
}
Michael Niedermayer
committed
return 0;
}
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
{
Baptiste Coudurier
committed
int ret = compute_pkt_fields2(s, s->streams[pkt->stream_index], pkt);
Michael Niedermayer
committed
if(ret<0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
Michael Niedermayer
committed
return ret;
if (ret >= 0)
s->streams[pkt->stream_index]->nb_frames++;
void ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt,
int (*compare)(AVFormatContext *, AVPacket *, AVPacket *))
{
AVPacketList **next_point, *this_pktl;
this_pktl = av_mallocz(sizeof(AVPacketList));
this_pktl->pkt= *pkt;
pkt->destruct= NULL; // do not free original but only the copy
av_dup_packet(&this_pktl->pkt); // duplicate the packet if it uses non-alloced memory
Michael Niedermayer
committed
if(s->streams[pkt->stream_index]->last_in_packet_buffer){
next_point = &(s->streams[pkt->stream_index]->last_in_packet_buffer->next);
}else
next_point = &s->packet_buffer;
Michael Niedermayer
committed
if(*next_point){
if(compare(s, &s->packet_buffer_end->pkt, pkt)){
while(!compare(s, &(*next_point)->pkt, pkt)){
next_point= &(*next_point)->next;
}
Michael Niedermayer
committed
goto next_non_null;
}else{
next_point = &(s->packet_buffer_end->next);
Michael Niedermayer
committed
}
}
s->packet_buffer_end= this_pktl;
Michael Niedermayer
committed
next_non_null:
Michael Niedermayer
committed
this_pktl->next= *next_point;
Michael Niedermayer
committed
s->streams[pkt->stream_index]->last_in_packet_buffer=
*next_point= this_pktl;
static int ff_interleave_compare_dts(AVFormatContext *s, AVPacket *next, AVPacket *pkt)
{
AVStream *st = s->streams[ pkt ->stream_index];
AVStream *st2= s->streams[ next->stream_index];
int comp = av_compare_ts(next->dts, st2->time_base, pkt->dts,
st->time_base);
if (comp == 0)
return pkt->stream_index < next->stream_index;
int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush){
AVPacketList *pktl;
Michael Niedermayer
committed
int stream_count=0;
int i;
Michael Niedermayer
committed
if(pkt){
ff_interleave_add_packet(s, pkt, ff_interleave_compare_dts);
Michael Niedermayer
committed
}
for(i=0; i < s->nb_streams; i++)
Michael Niedermayer
committed
stream_count+= !!s->streams[i]->last_in_packet_buffer;
if(stream_count && (s->nb_streams == stream_count || flush)){
Michael Niedermayer
committed
pktl= s->packet_buffer;
*out= pktl->pkt;
s->packet_buffer= pktl->next;
if(!s->packet_buffer)
s->packet_buffer_end= NULL;
Michael Niedermayer
committed
if(s->streams[out->stream_index]->last_in_packet_buffer == pktl)
s->streams[out->stream_index]->last_in_packet_buffer= NULL;
Michael Niedermayer
committed
av_freep(&pktl);
return 1;
}else{
av_init_packet(out);
return 0;
}
}
/**
* Interleave an AVPacket correctly so it can be muxed.
Michael Niedermayer
committed
* @param out the interleaved packet will be output here
* @param in the input packet
* @param flush 1 if no further packets are available as input and all
* remaining packets should be output
* @return 1 if a packet was output, 0 if no packet could be output,
Michael Niedermayer
committed
*/
static int interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, int flush){
Michael Niedermayer
committed
if(s->oformat->interleave_packet)
return s->oformat->interleave_packet(s, out, in, flush);
else
return av_interleave_packet_per_dts(s, out, in, flush);
}
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){
AVStream *st= s->streams[ pkt->stream_index];
int ret;
//FIXME/XXX/HACK drop zero sized packets
if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO && pkt->size==0)
Michael Niedermayer
committed
av_dlog(s, "av_interleaved_write_frame size:%d dts:%"PRId64" pts:%"PRId64"\n",
pkt->size, pkt->dts, pkt->pts);
if((ret = compute_pkt_fields2(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
return ret;
if(pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
return AVERROR(EINVAL);
Michael Niedermayer
committed
for(;;){
AVPacket opkt;
int ret= interleave_packet(s, &opkt, pkt, 0);
Michael Niedermayer
committed
if(ret<=0) //FIXME cleanup needed for ret<0 ?
return ret;
Michael Niedermayer
committed
ret= s->oformat->write_packet(s, &opkt);
if (ret >= 0)
s->streams[opkt.stream_index]->nb_frames++;
Michael Niedermayer
committed
av_free_packet(&opkt);
pkt= NULL;
if(ret<0)
return ret;
}
Fabrice Bellard
committed
}
int av_write_trailer(AVFormatContext *s)
{
int ret, i;
Michael Niedermayer
committed
for(;;){
AVPacket pkt;
ret= interleave_packet(s, &pkt, NULL, 1);
Michael Niedermayer
committed
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);
if (ret >= 0)
s->streams[pkt.stream_index]->nb_frames++;
Michael Niedermayer
committed
av_free_packet(&pkt);
goto fail;
if(s->oformat->write_trailer)
ret = s->oformat->write_trailer(s);
av_freep(&s->streams[i]->priv_data);
av_freep(&s->streams[i]->index_entries);
}
if (s->iformat && s->iformat->priv_class)
av_opt_free(s->priv_data);
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, AVDictionary *m, const char *indent)
if(m && !(m->count == 1 && av_dict_get(m, "language", NULL, 0))){
AVDictionaryEntry *tag=NULL;
av_log(ctx, AV_LOG_INFO, "%sMetadata:\n", indent);
while((tag=av_dict_get(m, "", tag, AV_DICT_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);
AVDictionaryEntry *lang = av_dict_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
}
if (st->disposition & AV_DISPOSITION_DEFAULT)
av_log(NULL, AV_LOG_INFO, " (default)");
if (st->disposition & AV_DISPOSITION_DUB)
av_log(NULL, AV_LOG_INFO, " (dub)");
if (st->disposition & AV_DISPOSITION_ORIGINAL)
av_log(NULL, AV_LOG_INFO, " (original)");
if (st->disposition & AV_DISPOSITION_COMMENT)
av_log(NULL, AV_LOG_INFO, " (comment)");
if (st->disposition & AV_DISPOSITION_LYRICS)
av_log(NULL, AV_LOG_INFO, " (lyrics)");
if (st->disposition & AV_DISPOSITION_KARAOKE)
av_log(NULL, AV_LOG_INFO, " (karaoke)");
if (st->disposition & AV_DISPOSITION_FORCED)
av_log(NULL, AV_LOG_INFO, " (forced)");
if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
av_log(NULL, AV_LOG_INFO, " (hearing impaired)");
if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
av_log(NULL, AV_LOG_INFO, " (visual impaired)");
if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
av_log(NULL, AV_LOG_INFO, " (clean effects)");
Nico Sabbi
committed
av_log(NULL, AV_LOG_INFO, "\n");
dump_metadata(NULL, st->metadata, " ");
Nico Sabbi
committed
}
{
av_dump_format(ic, index, url, is_output);
}
#endif
void av_dump_format(AVFormatContext *ic,
int index,
const char *url,
int is_output)
uint8_t *printed = ic->nb_streams ? av_mallocz(ic->nb_streams) : NULL;
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++) {
AVDictionaryEntry *name = av_dict_get(ic->programs[j]->metadata,
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);
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;
}
#if FF_API_PARSE_DATE
#include "libavutil/parseutils.h"
Philip Gladstone
committed
int64_t parse_date(const char *timestr, int duration)
{
int64_t timeval;
av_parse_time(&timeval, timestr, duration);
return timeval;
#if FF_API_FIND_INFO_TAG
#include "libavutil/parseutils.h"
int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
{
return av_find_info_tag(arg, arg_size, tag1, info);
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));
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
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
}
static void pkt_dump_internal(void *avcl, FILE *f, int level, AVPacket *pkt, int dump_payload, AVRational time_base)
#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));
PRINT(" duration=%0.3f\n", pkt->duration * av_q2d(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");
PRINT("%0.3f", pkt->dts * av_q2d(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");
PRINT("%0.3f", pkt->pts * av_q2d(time_base));
Panagiotis Issaris
committed
PRINT("\n");
PRINT(" size=%d\n", pkt->size);
#undef PRINT
if (dump_payload)
av_hex_dump(f, pkt->data, pkt->size);
}
#if FF_API_PKT_DUMP
Panagiotis Issaris
committed
void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload)
{
AVRational tb = { 1, AV_TIME_BASE };
pkt_dump_internal(NULL, f, 0, pkt, dump_payload, tb);
}
void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st)
{
pkt_dump_internal(NULL, f, 0, pkt, dump_payload, st->time_base);
Panagiotis Issaris
committed
}
#if FF_API_PKT_DUMP
Panagiotis Issaris
committed
void av_pkt_dump_log(void *avcl, int level, AVPacket *pkt, int dump_payload)
{
AVRational tb = { 1, AV_TIME_BASE };
pkt_dump_internal(avcl, NULL, level, pkt, dump_payload, tb);
}
void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload,
AVStream *st)
{
pkt_dump_internal(avcl, NULL, level, pkt, dump_payload, st->time_base);
Panagiotis Issaris
committed
}
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;
}
3731
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
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)
{
avpriv_set_pts_info(s, pts_wrap_bits, pts_num, pts_den);
}
#endif
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits,
unsigned int pts_num, unsigned int pts_den)
AVRational new_tb;
if(av_reduce(&new_tb.num, &new_tb.den, pts_num, pts_den, INT_MAX)){
if(new_tb.num != pts_num)
av_log(NULL, AV_LOG_DEBUG, "st:%d removing common factor %d from timebase\n", s->index, pts_num/new_tb.num);
}else
av_log(NULL, AV_LOG_WARNING, "st:%d has too large timebase, reducing\n", s->index);
if(new_tb.num <= 0 || new_tb.den <= 0) {
av_log(NULL, AV_LOG_ERROR, "Ignoring attempt to set invalid timebase for st:%d\n", s->index);
return;
}
s->time_base = new_tb;
s->pts_wrap_bits = pts_wrap_bits;
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])
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
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);
}
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
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;
}
}
int ff_find_stream_index(AVFormatContext *s, int id)
{
int i;
for (i = 0; i < s->nb_streams; i++) {
if (s->streams[i]->id == id)
return i;
}
return -1;
}
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
void ff_make_absolute_url(char *buf, int size, const char *base,
const char *rel)
{
char *sep;
/* Absolute path, relative to the current server */
if (base && strstr(base, "://") && rel[0] == '/') {
if (base != buf)
av_strlcpy(buf, base, size);
sep = strstr(buf, "://");
if (sep) {
sep += 3;
sep = strchr(sep, '/');
if (sep)
*sep = '\0';
}
av_strlcat(buf, rel, size);
return;
}
/* If rel actually is an absolute url, just copy it */
if (!base || strstr(rel, "://") || rel[0] == '/') {
av_strlcpy(buf, rel, size);
return;
}
if (base != buf)
av_strlcpy(buf, base, size);
/* Remove the file name from the base url */
sep = strrchr(buf, '/');
if (sep)
sep[1] = '\0';
else
buf[0] = '\0';
while (av_strstart(rel, "../", NULL) && sep) {
/* Remove the path delimiter at the end */
sep[0] = '\0';
sep = strrchr(buf, '/');
/* If the next directory name to pop off is "..", break here */
if (!strcmp(sep ? &sep[1] : buf, "..")) {
/* Readd the slash we just removed */
av_strlcat(buf, "/", size);
break;
}
/* Cut off the directory name */
if (sep)
sep[1] = '\0';
else
buf[0] = '\0';
rel += 3;
}
av_strlcat(buf, rel, size);
}
int64_t ff_iso8601_to_unix_time(const char *datestr)
{
struct tm time1 = {0}, time2 = {0};
char *ret1, *ret2;
ret1 = strptime(datestr, "%Y - %m - %d %T", &time1);
ret2 = strptime(datestr, "%Y - %m - %dT%T", &time2);
if (ret2 && !ret1)
return av_timegm(&time2);
else
return av_timegm(&time1);
#else
av_log(NULL, AV_LOG_WARNING, "strptime() unavailable on this system, cannot convert "
"the date string.\n");
return 0;
#endif
int avformat_query_codec(AVOutputFormat *ofmt, enum CodecID codec_id, int std_compliance)
{
if (ofmt) {
if (ofmt->query_codec)
return ofmt->query_codec(codec_id, std_compliance);
else if (ofmt->codec_tag)
return !!av_codec_get_tag(ofmt->codec_tag, codec_id);
else if (codec_id == ofmt->video_codec || codec_id == ofmt->audio_codec ||
codec_id == ofmt->subtitle_codec)
}
return AVERROR_PATCHWELCOME;
}
int avformat_network_init(void)
{
#if CONFIG_NETWORK
int ret;
ff_network_inited_globally = 1;
if ((ret = ff_network_init()) < 0)