mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
AV synchronisation API
Originally committed as revision 1054 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
3f9bff71b5
commit
916c80e94a
@ -14,7 +14,7 @@
|
||||
#define AV_NOPTS_VALUE 0
|
||||
|
||||
typedef struct AVPacket {
|
||||
INT64 pts;
|
||||
INT64 pts; /* presentation time stamp in stream units (set av_set_pts_info) */
|
||||
UINT8 *data;
|
||||
int size;
|
||||
int stream_index;
|
||||
@ -27,6 +27,19 @@ typedef struct AVPacket {
|
||||
int av_new_packet(AVPacket *pkt, int size);
|
||||
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 */
|
||||
|
||||
@ -151,6 +164,9 @@ typedef struct AVFormatContext {
|
||||
char copyright[512];
|
||||
char comment[512];
|
||||
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
|
||||
not decoded, for example to get the codec parameters in mpeg
|
||||
streams */
|
||||
@ -276,6 +292,8 @@ int av_find_stream_info(AVFormatContext *ic);
|
||||
int av_read_packet(AVFormatContext *s, AVPacket *pkt);
|
||||
void av_close_input_file(AVFormatContext *s);
|
||||
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 */
|
||||
int av_write_header(AVFormatContext *s);
|
||||
|
148
libav/utils.c
148
libav/utils.c
@ -153,7 +153,7 @@ int av_new_packet(AVPacket *pkt, int size)
|
||||
return AVERROR_NOMEM;
|
||||
pkt->size = size;
|
||||
/* sane state */
|
||||
pkt->pts = 0;
|
||||
pkt->pts = AV_NOPTS_VALUE;
|
||||
pkt->stream_index = 0;
|
||||
pkt->flags = 0;
|
||||
return 0;
|
||||
@ -356,6 +356,9 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
|
||||
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 */
|
||||
if (ic->iformat->flags & AVFMT_NEEDNUMBER) {
|
||||
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);
|
||||
if (!s->priv_data)
|
||||
return AVERROR_NOMEM;
|
||||
/* default pts settings is MPEG like */
|
||||
av_set_pts_info(s, 33, 1, 90000);
|
||||
return s->oformat->write_header(s);
|
||||
}
|
||||
|
||||
@ -829,11 +834,15 @@ static time_t mktimegm(struct tm *tm)
|
||||
return t;
|
||||
}
|
||||
|
||||
/* syntax:
|
||||
* [YYYY-MM-DD]{T| }HH[:MM[:SS[.m...]]][Z] .
|
||||
* [YYYYMMDD]{T| }HH[MM[SS[.m...]]][Z] .
|
||||
/* 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 */
|
||||
* Return the date in micro seconds since 1970
|
||||
* - If duration:
|
||||
* HH[:MM[:SS[.m...]]]
|
||||
* S+[.m...]
|
||||
*/
|
||||
INT64 parse_date(const char *datestr, int duration)
|
||||
{
|
||||
const char *p;
|
||||
@ -849,19 +858,21 @@ INT64 parse_date(const char *datestr, int duration)
|
||||
"%H%M%S",
|
||||
};
|
||||
const char *q;
|
||||
int is_utc;
|
||||
int is_utc, len;
|
||||
char lastch;
|
||||
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');
|
||||
|
||||
memset(&dt, 0, sizeof(dt));
|
||||
|
||||
p = datestr;
|
||||
q = 0;
|
||||
|
||||
q = NULL;
|
||||
if (!duration) {
|
||||
for (i = 0; i < sizeof(date_fmt) / sizeof(date_fmt[0]); i++) {
|
||||
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 == ' ')
|
||||
p++;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) {
|
||||
q = strptime(p, time_fmt[i], &dt);
|
||||
if (q) {
|
||||
break;
|
||||
for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) {
|
||||
q = strptime(p, time_fmt[i], &dt);
|
||||
if (q) {
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
@ -1134,3 +1123,74 @@ void url_split(char *proto, int proto_size,
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user