Originally committed as revision 1058 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
@@ -84,6 +84,7 @@ typedef struct AVOutputFormat { | |||
enum CodecID audio_codec; /* default audio codec */ | |||
enum CodecID video_codec; /* default video codec */ | |||
int (*write_header)(struct AVFormatContext *); | |||
/* XXX: change prototype for 64 bit pts */ | |||
int (*write_packet)(struct AVFormatContext *, | |||
int stream_index, | |||
unsigned char *buf, int size, int force_pts); | |||
@@ -142,6 +143,8 @@ typedef struct AVStream { | |||
int codec_info_state; | |||
int codec_info_nb_repeat_frames; | |||
int codec_info_nb_real_frames; | |||
/* PTS generation when outputing stream */ | |||
AVFrac pts; | |||
/* ffmpeg.c private use */ | |||
int stream_copy; /* if TRUE, just copy stream */ | |||
} AVStream; | |||
@@ -297,7 +300,8 @@ void av_set_pts_info(AVFormatContext *s, int pts_wrap_bits, | |||
/* media file output */ | |||
int av_write_header(AVFormatContext *s); | |||
int av_write_packet(AVFormatContext *s, AVPacket *pkt, int force_pts); | |||
int av_write_frame(AVFormatContext *s, int stream_index, const uint8_t *buf, | |||
int size); | |||
int av_write_trailer(AVFormatContext *s); | |||
void dump_format(AVFormatContext *ic, | |||
@@ -1,57 +0,0 @@ | |||
/* tick.h - Compute successive integer multiples of a rational | |||
* number without long-term rounding error. | |||
* (c)2002 by Lennert Buytenhek <buytenh@gnu.org> | |||
* File licensed under the GPL, see http://www.fsf.org/ for more info. | |||
* Dedicated to Marija Kulikova. | |||
*/ | |||
#include "avcodec.h" | |||
typedef struct Ticker { | |||
int value; | |||
int inrate; | |||
int outrate; | |||
int div; | |||
int mod; | |||
} Ticker; | |||
extern void ticker_init(Ticker *tick, INT64 inrate, INT64 outrate); | |||
static inline int ticker_tick(Ticker *tick, int num) | |||
{ | |||
int n = num * tick->div; | |||
tick->value += num * tick->mod; | |||
#if 1 | |||
if (tick->value > 0) { | |||
n += (tick->value / tick->inrate); | |||
tick->value = tick->value % tick->inrate; | |||
if (tick->value > 0) { | |||
tick->value -= tick->inrate; | |||
n++; | |||
} | |||
} | |||
#else | |||
while (tick->value > 0) { | |||
tick->value -= tick->inrate; | |||
n++; | |||
} | |||
#endif | |||
return n; | |||
} | |||
static inline INT64 ticker_abs(Ticker *tick, int num) | |||
{ | |||
INT64 n = (INT64) num * tick->div; | |||
INT64 value = (INT64) num * tick->mod; | |||
if (value > 0) { | |||
n += (value / tick->inrate); | |||
value = value % tick->inrate; | |||
if (value > 0) { | |||
/* value -= tick->inrate; */ | |||
n++; | |||
} | |||
} | |||
return n; | |||
} |
@@ -17,7 +17,6 @@ | |||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
*/ | |||
#include "avformat.h" | |||
#include "tick.h" | |||
#include <ctype.h> | |||
#ifndef CONFIG_WIN32 | |||
#include <unistd.h> | |||
@@ -695,25 +694,76 @@ AVStream *av_new_stream(AVFormatContext *s, int id) | |||
*/ | |||
int av_write_header(AVFormatContext *s) | |||
{ | |||
int ret, i; | |||
AVStream *st; | |||
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); | |||
ret = s->oformat->write_header(s); | |||
if (ret < 0) | |||
return ret; | |||
/* init PTS generation */ | |||
for(i=0;i<s->nb_streams;i++) { | |||
st = s->streams[i]; | |||
switch (st->codec.codec_type) { | |||
case CODEC_TYPE_AUDIO: | |||
av_frac_init(&st->pts, 0, 0, | |||
(INT64)s->pts_num * st->codec.sample_rate); | |||
break; | |||
case CODEC_TYPE_VIDEO: | |||
av_frac_init(&st->pts, 0, 0, | |||
(INT64)s->pts_num * st->codec.frame_rate); | |||
break; | |||
default: | |||
break; | |||
} | |||
} | |||
return 0; | |||
} | |||
/** | |||
* write a packet to an output media file | |||
* Write a packet to an output media file. The packet shall contain | |||
* one audio or video frame. | |||
* | |||
* @param s media file handle | |||
* @param pkt packet to write | |||
* @param force_pts XXX: need to suppress that | |||
* @param stream_index stream index | |||
* @param buf buffer containing the frame data | |||
* @param size size of buffer | |||
* @return non zero if error. | |||
*/ | |||
int av_write_packet(AVFormatContext *s, AVPacket *pkt, int force_pts) | |||
int av_write_frame(AVFormatContext *s, int stream_index, const uint8_t *buf, | |||
int size) | |||
{ | |||
/* XXX: currently, an emulation because internal API must change */ | |||
return s->oformat->write_packet(s, pkt->stream_index, pkt->data, pkt->size, force_pts); | |||
AVStream *st; | |||
INT64 pts_mask; | |||
int ret; | |||
st = s->streams[stream_index]; | |||
pts_mask = (1LL << s->pts_wrap_bits) - 1; | |||
ret = s->oformat->write_packet(s, stream_index, (uint8_t *)buf, size, | |||
st->pts.val & pts_mask); | |||
if (ret < 0) | |||
return ret; | |||
/* update pts */ | |||
switch (st->codec.codec_type) { | |||
case CODEC_TYPE_AUDIO: | |||
av_frac_add(&st->pts, | |||
(INT64)s->pts_den * st->codec.frame_size); | |||
break; | |||
case CODEC_TYPE_VIDEO: | |||
av_frac_add(&st->pts, | |||
(INT64)s->pts_den * FRAME_RATE_BASE); | |||
break; | |||
default: | |||
break; | |||
} | |||
return 0; | |||
} | |||
/** | |||