pass AVPacket into av_write_frame()

fixes the random dts/pts during encoding
asf preroll fix
no more initial zero frames for b frame encoding
mpeg-es dts during demuxing fixed
.ffm timestamp scale fixed, ffm is still broken though

Originally committed as revision 3168 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Michael Niedermayer
2004-05-29 02:06:32 +00:00
parent a7b2871cd1
commit e928649b0b
33 changed files with 328 additions and 245 deletions

150
ffmpeg.c
View File

@@ -230,9 +230,8 @@ typedef struct AVOutputStream {
int frame_number;
/* input pts and corresponding output pts
for A/V sync */
double sync_ipts;
double sync_ipts_offset;
int64_t sync_opts;
double sync_ipts; /* dts from the AVPacket of the demuxer in second units */
int64_t sync_opts; /* output frame counter, could be changed to some true timestamp */ //FIXME look at frame_number
/* video only */
int video_resample; /* video_resample and video_crop are mutually exclusive */
AVFrame pict_tmp; /* temporary image for resampling */
@@ -447,12 +446,23 @@ static void do_audio_out(AVFormatContext *s,
while (fifo_read(&ost->fifo, audio_buf, frame_bytes,
&ost->fifo.rptr) == 0) {
AVPacket pkt;
av_init_packet(&pkt);
ret = avcodec_encode_audio(enc, audio_out, audio_out_size,
(short *)audio_buf);
audio_size += ret;
av_write_frame(s, ost->index, audio_out, ret);
pkt.stream_index= ost->index;
pkt.data= audio_out;
pkt.size= ret;
if(enc->coded_frame)
pkt.pts= enc->coded_frame->pts;
pkt.flags |= PKT_FLAG_KEY;
av_write_frame(s, &pkt);
}
} else {
AVPacket pkt;
av_init_packet(&pkt);
/* output a pcm frame */
/* XXX: change encoding codec API to avoid this ? */
switch(enc->codec->id) {
@@ -468,7 +478,13 @@ static void do_audio_out(AVFormatContext *s,
ret = avcodec_encode_audio(enc, audio_out, size_out,
(short *)buftmp);
audio_size += ret;
av_write_frame(s, ost->index, audio_out, ret);
pkt.stream_index= ost->index;
pkt.data= audio_out;
pkt.size= ret;
if(enc->coded_frame)
pkt.pts= enc->coded_frame->pts;
pkt.flags |= PKT_FLAG_KEY;
av_write_frame(s, &pkt);
}
}
@@ -586,58 +602,17 @@ static void do_video_out(AVFormatContext *s,
*frame_size = 0;
/* NOTE: the A/V sync is always done by considering the audio is
the master clock. It is suffisant for transcoding or playing,
but not for the general case */
if(sync_method){
if (audio_sync) {
/* compute the A-V delay and duplicate/remove frames if needed */
double adelta, vdelta, av_delay;
adelta = audio_sync->sync_ipts - ((double)audio_sync->sync_opts *
audio_sync->st->time_base.num / audio_sync->st->time_base.den);
vdelta = ost->sync_ipts - ((double)ost->sync_opts *
ost->st->time_base.num / ost->st->time_base.den);
av_delay = adelta - vdelta;
if (av_delay < -AV_DELAY_MAX)
nb_frames = 2;
else if (av_delay > AV_DELAY_MAX)
nb_frames = 0;
// printf("adelta=%f vdelta=%f delay=%f nb=%d (A)\n", adelta, vdelta, av_delay, nb_frames);
} else {
if(sync_method){
double vdelta;
vdelta = (double)(ost->st->pts.val) * ost->st->time_base.num / ost->st->time_base.den - (ost->sync_ipts - ost->sync_ipts_offset);
if (vdelta < 100 && vdelta > -100 && ost->sync_ipts_offset) {
if (vdelta < -AV_DELAY_MAX)
nb_frames = 2;
else if (vdelta > AV_DELAY_MAX)
nb_frames = 0;
} else {
ost->sync_ipts_offset -= vdelta;
if (!ost->sync_ipts_offset)
ost->sync_ipts_offset = 0.000001; /* one microsecond */
}
// printf("delay=%f nb=%d (V)\n",vdelta, nb_frames);
vdelta = ost->sync_ipts * enc->frame_rate / enc->frame_rate_base - ost->sync_opts;
//FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
if (vdelta < -1.1)
nb_frames = 0;
else if (vdelta > 1.1)
nb_frames = 2;
//printf("vdelta:%f, ost->sync_opts:%lld, ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, ost->sync_ipts, nb_frames);
}
}
#if defined(AVSYNC_DEBUG)
{
static char *action[] = { "drop frame", "copy frame", "dup frame" };
if (audio_sync && verbose >=0) {
fprintf(stderr, "Input APTS %12.6f, output APTS %12.6f, ",
(double) audio_sync->sync_ipts,
(double) audio_sync->st->pts.val * st->time_base.num / st->time_base.den);
fprintf(stderr, "Input VPTS %12.6f, output VPTS %12.6f: %s\n",
(double) ost->sync_ipts,
(double) ost->st->pts.val * st->time_base.num / st->time_base.den,
action[nb_frames]);
}
}
#endif
ost->sync_opts+= nb_frames;
if (nb_frames <= 0)
return;
@@ -779,14 +754,24 @@ static void do_video_out(AVFormatContext *s,
/* duplicates frame if needed */
/* XXX: pb because no interleaving */
for(i=0;i<nb_frames;i++) {
AVPacket pkt;
av_init_packet(&pkt);
pkt.stream_index= ost->index;
if (s->oformat->flags & AVFMT_RAWPICTURE) {
/* raw pictures are written as AVPicture structure to
avoid any copies. We support temorarily the older
method. */
AVFrame* old_frame = enc->coded_frame;
enc->coded_frame = dec->coded_frame;
av_write_frame(s, ost->index,
(uint8_t *)final_picture, sizeof(AVPicture));
enc->coded_frame = dec->coded_frame; //FIXME/XXX remove this hack
pkt.data= (uint8_t *)final_picture;
pkt.size= sizeof(AVPicture);
if(dec->coded_frame)
pkt.pts= dec->coded_frame->pts;
if(dec->coded_frame && dec->coded_frame->key_frame)
pkt.flags |= PKT_FLAG_KEY;
av_write_frame(s, &pkt);
enc->coded_frame = old_frame;
} else {
AVFrame big_picture;
@@ -815,14 +800,22 @@ static void do_video_out(AVFormatContext *s,
video_buffer, VIDEO_BUFFER_SIZE,
&big_picture);
//enc->frame_number = enc->real_pict_num;
av_write_frame(s, ost->index, video_buffer, ret);
*frame_size = ret;
//fprintf(stderr,"\nFrame: %3d %3d size: %5d type: %d",
// enc->frame_number-1, enc->real_pict_num, ret,
// enc->pict_type);
/* if two pass, output log */
if (ost->logfile && enc->stats_out) {
fprintf(ost->logfile, "%s", enc->stats_out);
if(ret){
pkt.data= video_buffer;
pkt.size= ret;
if(enc->coded_frame)
pkt.pts= enc->coded_frame->pts;
if(enc->coded_frame && enc->coded_frame->key_frame)
pkt.flags |= PKT_FLAG_KEY;
av_write_frame(s, &pkt);
*frame_size = ret;
//fprintf(stderr,"\nFrame: %3d %3d size: %5d type: %d",
// enc->frame_number-1, enc->real_pict_num, ret,
// enc->pict_type);
/* if two pass, output log */
if (ost->logfile && enc->stats_out) {
fprintf(ost->logfile, "%s", enc->stats_out);
}
}
}
ost->frame_number++;
@@ -872,7 +865,7 @@ static void do_video_stats(AVFormatContext *os, AVOutputStream *ost,
fprintf(fvstats,"f_size= %6d ", frame_size);
/* compute pts value */
ti1 = (double)ost->st->pts.val * ost->st->time_base.num / ost->st->time_base.den;
ti1 = (double)ost->sync_opts *enc->frame_rate_base / enc->frame_rate;
if (ti1 < 0.01)
ti1 = 0.01;
@@ -1003,8 +996,8 @@ static int output_packet(AVInputStream *ist, int ist_index,
short samples[AVCODEC_MAX_AUDIO_FRAME_SIZE / 2];
void *buffer_to_free;
if (pkt && pkt->pts != AV_NOPTS_VALUE) {
ist->next_pts = ist->pts = pkt->pts;
if (pkt && pkt->pts != AV_NOPTS_VALUE) { //FIXME seems redundant, as libavformat does this too
ist->next_pts = ist->pts = pkt->dts;
} else {
ist->pts = ist->next_pts;
}
@@ -1122,10 +1115,6 @@ static int output_packet(AVInputStream *ist, int ist_index,
#endif
/* set the input output pts pairs */
ost->sync_ipts = (double)ist->pts / AV_TIME_BASE;
/* XXX: take into account the various fifos,
in particular for audio */
ost->sync_opts = ost->st->pts.val;
//printf("ipts=%lld sync_ipts=%f sync_opts=%lld pts.val=%lld pkt->pts=%lld\n", ist->pts, ost->sync_ipts, ost->sync_opts, ost->st->pts.val, pkt->pts);
if (ost->encoding_needed) {
switch(ost->st->codec.codec_type) {
@@ -1157,22 +1146,29 @@ static int output_packet(AVInputStream *ist, int ist_index,
av_abort();
}
} else {
AVFrame avframe;
AVFrame avframe; //FIXME/XXX remove this
AVPacket opkt;
av_init_packet(&opkt);
/* no reencoding needed : output the packet directly */
/* force the input stream PTS */
avcodec_get_frame_defaults(&avframe);
ost->st->codec.coded_frame= &avframe;
avframe.key_frame = pkt->flags & PKT_FLAG_KEY;
ost->st->pts.val= av_rescale(ist->pts, ost->st->time_base.den, ost->st->time_base.num*AV_TIME_BASE);
if(ost->st->codec.codec_type == CODEC_TYPE_AUDIO)
audio_size += data_size;
else if (ost->st->codec.codec_type == CODEC_TYPE_VIDEO)
video_size += data_size;
av_write_frame(os, ost->index, data_buf, data_size);
opkt.stream_index= ost->index;
opkt.data= data_buf;
opkt.size= data_size;
opkt.pts= ist->pts; //FIXME dts vs. pts
opkt.flags= pkt->flags;
av_write_frame(os, &opkt);
ost->st->codec.frame_number++;
ost->frame_number++;
}