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 audio_codec; /* default audio codec */ | ||||
| enum CodecID video_codec; /* default video codec */ | enum CodecID video_codec; /* default video codec */ | ||||
| int (*write_header)(struct AVFormatContext *); | int (*write_header)(struct AVFormatContext *); | ||||
| /* XXX: change prototype for 64 bit pts */ | |||||
| int (*write_packet)(struct AVFormatContext *, | int (*write_packet)(struct AVFormatContext *, | ||||
| int stream_index, | int stream_index, | ||||
| unsigned char *buf, int size, int force_pts); | unsigned char *buf, int size, int force_pts); | ||||
| @@ -142,6 +143,8 @@ typedef struct AVStream { | |||||
| int codec_info_state; | int codec_info_state; | ||||
| int codec_info_nb_repeat_frames; | int codec_info_nb_repeat_frames; | ||||
| int codec_info_nb_real_frames; | int codec_info_nb_real_frames; | ||||
| /* PTS generation when outputing stream */ | |||||
| AVFrac pts; | |||||
| /* ffmpeg.c private use */ | /* ffmpeg.c private use */ | ||||
| int stream_copy; /* if TRUE, just copy stream */ | int stream_copy; /* if TRUE, just copy stream */ | ||||
| } AVStream; | } AVStream; | ||||
| @@ -297,7 +300,8 @@ void av_set_pts_info(AVFormatContext *s, int pts_wrap_bits, | |||||
| /* media file output */ | /* media file output */ | ||||
| int av_write_header(AVFormatContext *s); | 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); | int av_write_trailer(AVFormatContext *s); | ||||
| void dump_format(AVFormatContext *ic, | 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 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
| */ | */ | ||||
| #include "avformat.h" | #include "avformat.h" | ||||
| #include "tick.h" | |||||
| #include <ctype.h> | #include <ctype.h> | ||||
| #ifndef CONFIG_WIN32 | #ifndef CONFIG_WIN32 | ||||
| #include <unistd.h> | #include <unistd.h> | ||||
| @@ -695,25 +694,76 @@ AVStream *av_new_stream(AVFormatContext *s, int id) | |||||
| */ | */ | ||||
| int av_write_header(AVFormatContext *s) | int av_write_header(AVFormatContext *s) | ||||
| { | { | ||||
| int ret, i; | |||||
| AVStream *st; | |||||
| 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 */ | /* default pts settings is MPEG like */ | ||||
| av_set_pts_info(s, 33, 1, 90000); | 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 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; | |||||
| } | } | ||||
| /** | /** | ||||