AV synchronisation API

Originally committed as revision 1054 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Fabrice Bellard 2002-10-21 15:54:49 +00:00
parent 3f9bff71b5
commit 916c80e94a
2 changed files with 123 additions and 45 deletions

View File

@ -14,7 +14,7 @@
#define AV_NOPTS_VALUE 0 #define AV_NOPTS_VALUE 0
typedef struct AVPacket { typedef struct AVPacket {
INT64 pts; INT64 pts; /* presentation time stamp in stream units (set av_set_pts_info) */
UINT8 *data; UINT8 *data;
int size; int size;
int stream_index; int stream_index;
@ -27,6 +27,19 @@ typedef struct AVPacket {
int av_new_packet(AVPacket *pkt, int size); int av_new_packet(AVPacket *pkt, int size);
void av_free_packet(AVPacket *pkt); void av_free_packet(AVPacket *pkt);
/*************************************************/
/* fractional numbers for exact pts handling */
/* the exact value of the fractional number is: 'val + num / den'. num
is assumed to be such as 0 <= num < den */
typedef struct AVFrac {
INT64 val, num, den;
} AVFrac;
void av_frac_init(AVFrac *f, INT64 val, INT64 num, INT64 den);
void av_frac_add(AVFrac *f, INT64 incr);
void av_frac_set(AVFrac *f, INT64 val);
/*************************************************/ /*************************************************/
/* input/output formats */ /* input/output formats */
@ -151,6 +164,9 @@ typedef struct AVFormatContext {
char copyright[512]; char copyright[512];
char comment[512]; char comment[512];
int flags; /* format specific flags */ int flags; /* format specific flags */
/* private data for pts handling (do not modify directly) */
int pts_wrap_bits; /* number of bits in pts (used for wrapping control) */
int pts_num, pts_den; /* value to convert to seconds */
/* This buffer is only needed when packets were already buffered but /* This buffer is only needed when packets were already buffered but
not decoded, for example to get the codec parameters in mpeg not decoded, for example to get the codec parameters in mpeg
streams */ streams */
@ -276,6 +292,8 @@ int av_find_stream_info(AVFormatContext *ic);
int av_read_packet(AVFormatContext *s, AVPacket *pkt); int av_read_packet(AVFormatContext *s, AVPacket *pkt);
void av_close_input_file(AVFormatContext *s); void av_close_input_file(AVFormatContext *s);
AVStream *av_new_stream(AVFormatContext *s, int id); AVStream *av_new_stream(AVFormatContext *s, int id);
void av_set_pts_info(AVFormatContext *s, int pts_wrap_bits,
int pts_num, int pts_den);
/* media file output */ /* media file output */
int av_write_header(AVFormatContext *s); int av_write_header(AVFormatContext *s);

View File

@ -153,7 +153,7 @@ int av_new_packet(AVPacket *pkt, int size)
return AVERROR_NOMEM; return AVERROR_NOMEM;
pkt->size = size; pkt->size = size;
/* sane state */ /* sane state */
pkt->pts = 0; pkt->pts = AV_NOPTS_VALUE;
pkt->stream_index = 0; pkt->stream_index = 0;
pkt->flags = 0; pkt->flags = 0;
return 0; return 0;
@ -356,6 +356,9 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
goto fail; goto fail;
} }
/* default pts settings is MPEG like */
av_set_pts_info(ic, 33, 1, 90000);
/* check filename in case of an image number is expected */ /* check filename in case of an image number is expected */
if (ic->iformat->flags & AVFMT_NEEDNUMBER) { if (ic->iformat->flags & AVFMT_NEEDNUMBER) {
if (filename_number_test(ic->filename) < 0) { if (filename_number_test(ic->filename) < 0) {
@ -695,6 +698,8 @@ int av_write_header(AVFormatContext *s)
s->priv_data = av_mallocz(s->oformat->priv_data_size); s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (!s->priv_data) if (!s->priv_data)
return AVERROR_NOMEM; return AVERROR_NOMEM;
/* default pts settings is MPEG like */
av_set_pts_info(s, 33, 1, 90000);
return s->oformat->write_header(s); return s->oformat->write_header(s);
} }
@ -829,11 +834,15 @@ static time_t mktimegm(struct tm *tm)
return t; return t;
} }
/* syntax: /* Syntax:
* [YYYY-MM-DD]{T| }HH[:MM[:SS[.m...]]][Z] . * - If not a duration:
* [YYYYMMDD]{T| }HH[MM[SS[.m...]]][Z] . * [{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 * Time is localtime unless Z is suffixed to the end. In this case GMT
* Return the date in micro seconds since 1970 */ * Return the date in micro seconds since 1970
* - If duration:
* HH[:MM[:SS[.m...]]]
* S+[.m...]
*/
INT64 parse_date(const char *datestr, int duration) INT64 parse_date(const char *datestr, int duration)
{ {
const char *p; const char *p;
@ -849,19 +858,21 @@ INT64 parse_date(const char *datestr, int duration)
"%H%M%S", "%H%M%S",
}; };
const char *q; const char *q;
int is_utc; int is_utc, len;
char lastch; char lastch;
time_t now = time(0); time_t now = time(0);
lastch = datestr[strlen(datestr)-1]; len = strlen(datestr);
if (len > 0)
lastch = datestr[len - 1];
else
lastch = '\0';
is_utc = (lastch == 'z' || lastch == 'Z'); is_utc = (lastch == 'z' || lastch == 'Z');
memset(&dt, 0, sizeof(dt)); memset(&dt, 0, sizeof(dt));
p = datestr; p = datestr;
q = 0; q = NULL;
if (!duration) { if (!duration) {
for (i = 0; i < sizeof(date_fmt) / sizeof(date_fmt[0]); i++) { for (i = 0; i < sizeof(date_fmt) / sizeof(date_fmt[0]); i++) {
q = strptime(p, date_fmt[i], &dt); q = strptime(p, date_fmt[i], &dt);
@ -883,12 +894,19 @@ INT64 parse_date(const char *datestr, int duration)
if (*p == 'T' || *p == 't' || *p == ' ') if (*p == 'T' || *p == 't' || *p == ' ')
p++; p++;
}
for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) { for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) {
q = strptime(p, time_fmt[i], &dt); q = strptime(p, time_fmt[i], &dt);
if (q) { if (q) {
break; break;
}
}
} else {
q = strptime(p, time_fmt[0], &dt);
if (!q) {
dt.tm_sec = strtol(p, (char **)&q, 10);
dt.tm_min = 0;
dt.tm_hour = 0;
} }
} }
@ -1022,35 +1040,6 @@ int get_frame_filename(char *buf, int buf_size,
return -1; return -1;
} }
static int gcd(INT64 a, INT64 b)
{
INT64 c;
while (1) {
c = a % b;
if (c == 0)
return b;
a = b;
b = c;
}
}
void ticker_init(Ticker *tick, INT64 inrate, INT64 outrate)
{
int g;
g = gcd(inrate, outrate);
inrate /= g;
outrate /= g;
tick->value = -outrate/2;
tick->inrate = inrate;
tick->outrate = outrate;
tick->div = tick->outrate / tick->inrate;
tick->mod = tick->outrate % tick->inrate;
}
/** /**
* *
* Print on stdout a nice hexa dump of a buffer * Print on stdout a nice hexa dump of a buffer
@ -1134,3 +1123,74 @@ void url_split(char *proto, int proto_size,
pstrcpy(path, path_size, p); pstrcpy(path, path_size, p);
} }
/**
* Set the pts for a given stream
* @param s stream
* @param pts_wrap_bits number of bits effectively used by the pts
* (used for wrap control, 33 is the value for MPEG)
* @param pts_num numerator to convert to seconds (MPEG: 1)
* @param pts_den denominator to convert to seconds (MPEG: 90000)
*/
void av_set_pts_info(AVFormatContext *s, int pts_wrap_bits,
int pts_num, int pts_den)
{
s->pts_wrap_bits = pts_wrap_bits;
s->pts_num = pts_num;
s->pts_den = pts_den;
}
/* fraction handling */
/**
* f = val + (num / den) + 0.5. 'num' is normalized so that it is such
* as 0 <= num < den.
*
* @param f fractional number
* @param val integer value
* @param num must be >= 0
* @param den must be >= 1
*/
void av_frac_init(AVFrac *f, INT64 val, INT64 num, INT64 den)
{
num += (den >> 1);
if (num >= den) {
val += num / den;
num = num % den;
}
f->val = val;
f->num = num;
f->den = den;
}
/* set f to (val + 0.5) */
void av_frac_set(AVFrac *f, INT64 val)
{
f->val = val;
f->num = f->den >> 1;
}
/**
* Fractionnal addition to f: f = f + (incr / f->den)
*
* @param f fractional number
* @param incr increment, can be positive or negative
*/
void av_frac_add(AVFrac *f, INT64 incr)
{
INT64 num, den;
num = f->num + incr;
den = f->den;
if (num < 0) {
f->val += num / den;
num = num % den;
if (num < 0) {
num += den;
f->val--;
}
} else if (num >= den) {
f->val += num / den;
num = num % den;
}
f->num = num;
}