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
|
#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);
|
||||||
|
140
libav/utils.c
140
libav/utils.c
@ -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,7 +894,6 @@ 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);
|
||||||
@ -891,6 +901,14 @@ INT64 parse_date(const char *datestr, int duration)
|
|||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Now we have all the fields that we can get */
|
/* Now we have all the fields that we can get */
|
||||||
if (!q) {
|
if (!q) {
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user