new code to simplify assignment of timestamps; removed temp_ref from mpeg_frame_t and modified add_frame() accordingly; removed no more used drop_delayed_audio() and save_delayed_audio()

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@18182 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
nicodvb 2006-04-22 13:05:01 +00:00
parent 830ce1eb08
commit f86a32a270
1 changed files with 133 additions and 258 deletions

View File

@ -93,7 +93,6 @@ typedef struct {
size_t size;
size_t alloc_size;
uint8_t type;
uint32_t temp_ref;
uint64_t pts, dts, idur;
uint32_t pos; //start offset for the frame
} mpeg_frame_t;
@ -144,12 +143,13 @@ typedef struct {
typedef struct {
int has_pts, has_dts, pes_is_aligned, type, is_late, min_pes_hlen, psm_fixed;
int real_framerate, delay_rff;
uint64_t pts, last_pts, last_dts, dts, init_pts, init_dts, size, frame_duration, delta_pts, nom_delta_pts, frame_size, last_saved_pts;
uint64_t pts, last_pts, last_dts, dts, size, frame_duration, delta_pts, nom_delta_pts, frame_size, last_saved_pts;
uint32_t buffer_size;
uint8_t pes_priv_headers[4], has_pes_priv_headers; //for A52 and LPCM
uint32_t bitrate, rest;
int32_t compensate;
double delta_clock, timer, aframe_delta_pts, last_dpts;
int drop_delayed_frames;
mpeg_frame_t *framebuf;
uint16_t framebuf_cnt;
uint16_t framebuf_used;
@ -160,6 +160,7 @@ typedef struct {
uint64_t vframes;
uint8_t trf;
mp_mpeg_header_t picture;
int is_ready;
} muxer_headers_t;
#define PULLDOWN32 1
@ -314,7 +315,7 @@ static mpeg_frame_t *init_frames(uint16_t num, size_t size)
}
static uint32_t calc_pack_hlen(muxer_priv_t *priv, muxer_headers_t *h);
static int add_frame(muxer_headers_t *spriv, uint64_t idur, uint8_t *ptr, int len, uint8_t pt, uint32_t temp_ref);
static int add_frame(muxer_headers_t *spriv, uint64_t idur, uint8_t *ptr, int len, uint8_t pt, uint64_t dts, uint64_t pts);
static muxer_stream_t* mpegfile_new_stream(muxer_t *muxer,int type){
muxer_priv_t *priv;
@ -366,14 +367,7 @@ static muxer_stream_t* mpegfile_new_stream(muxer_t *muxer,int type){
if (type == MUXER_TYPE_VIDEO) {
spriv->type = 1;
spriv->init_dts = 0;
spriv->init_pts = conf_init_vpts * 90 * 300;
spriv->last_pts = spriv->init_pts;
spriv->last_saved_pts = 0;
spriv->init_dts = spriv->last_dts = spriv->init_pts;
spriv->pts = spriv->dts = 0;
spriv->last_dpts = spriv->timer;
spriv->delta_pts = spriv->nom_delta_pts = 0;
spriv->last_pts = conf_init_vpts * 90 * 300;
spriv->id = 0xe0 + muxer->num_videos;
s->ckid = be2me_32 (0x100 + spriv->id);
if(priv->is_genmpeg1 || priv->is_genmpeg2) {
@ -405,12 +399,12 @@ static muxer_stream_t* mpegfile_new_stream(muxer_t *muxer,int type){
} else { // MUXER_TYPE_AUDIO
spriv->type = 0;
spriv->pts = 1;
spriv->dts = 0;
spriv->max_pl_size = priv->packet_size - calc_pack_hlen(priv, spriv);
spriv->init_pts = conf_init_apts * 90 * 300;
spriv->pts = spriv->init_pts;
spriv->last_pts = spriv->init_pts;
spriv->dts = 0;
spriv->drop_delayed_frames = conf_drop;
spriv->last_pts = conf_init_apts * 90 * 300;
if(conf_init_adelay < 0 && ! spriv->drop_delayed_frames)
spriv->last_pts += (-conf_init_adelay) * 90 * 300;
spriv->pts = spriv->last_pts;
spriv->id = 0xc0 + muxer->num_audios;
s->ckid = be2me_32 (0x100 + spriv->id);
if(priv->is_genmpeg1 || priv->is_genmpeg2) {
@ -1154,57 +1148,6 @@ static uint32_t dump_audio(muxer_t *muxer, muxer_stream_t *as, uint32_t abytes,
return len;
}
static void drop_delayed_audio(muxer_t *muxer, muxer_stream_t *as, int64_t size)
{
//muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
muxer_headers_t *apriv = (muxer_headers_t *) as->priv;
int64_t size1, div, rest; //initial value
double rest_pts;
div = size / apriv->frame_size;
rest = size % apriv->frame_size;
if(rest >= apriv->frame_size / 2)
size1 = (div+1) * apriv->frame_size;
else
size1 = (div) * apriv->frame_size;
mp_msg(MSGT_MUXER, MSGL_V, "SIZE1: %"PRIu64", LEN: %"PRIu64"\n", size1, (uint64_t)as->b_buffer_len);
size1 = min(size1, as->b_buffer_len);
memmove(as->b_buffer, &(as->b_buffer[size]), as->b_buffer_len - size1);
as->b_buffer_len -= size1;
rest = size1 - size;
rest_pts = (double) rest / (double) apriv->bitrate;
apriv->pts += (int64_t) (27000000.0 * rest_pts);
apriv->last_pts += (int64_t) (27000000.0 * rest_pts);
mp_msg(MSGT_MUXER, MSGL_DBG2, "DROPPED: %"PRId64" bytes, REST= %"PRId64", REST_PTS: %.3lf, AUDIO_PTS%.3lf\n", size1, rest, rest_pts, (double) (apriv->pts/27000000.0));
}
static void save_delayed_audio(muxer_t *muxer, muxer_stream_t *as, uint64_t dur)
{
muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
muxer_headers_t *apriv = (muxer_headers_t *) as->priv;
uint64_t init_pts, last_pts; //initial value
init_pts = apriv->pts;
mp_msg(MSGT_MUXER, MSGL_DBG2, "DUR: %"PRIu64", DIFF: %"PRIu64"\n", dur, apriv->pts - init_pts);
while(dur > apriv->pts - init_pts)
{
priv->scr = (27000000 * apriv->size) / apriv->bitrate;
last_pts = apriv->pts;
dump_audio(muxer, as, as->b_buffer_len, 0);
mp_msg(MSGT_MUXER, MSGL_DBG2, "DUR: %"PRIu64", DIFF: %"PRIu64", SCR: %"PRIu64"\n", dur, apriv->pts - init_pts, priv->scr);
}
//priv->init_delay_pts = last_pts;
priv->init_delay_pts = (90 * 300 * abs(conf_init_adelay)) + apriv->init_pts - (90 * 300 * abs(conf_init_vpts));
if(priv->init_delay_pts <= priv->scr)
priv->init_delay_pts = last_pts;
mp_msg(MSGT_MUXER, MSGL_INFO, "INIT_VPTS: %"PRIu64" (%.3lf)\n", priv->init_delay_pts, (double) (priv->init_delay_pts/27000000.0));
}
static inline void update_scr(muxer_priv_t *priv, uint32_t len, uint32_t totlen, double mult)
{
uint64_t delta_scr;
@ -1231,9 +1174,9 @@ static int calc_frames_to_flush(muxer_headers_t *vpriv)
mp_msg(MSGT_MUXER, MSGL_DBG2, "\n");
while(n < vpriv->framebuf_used)
{
mp_msg(MSGT_MUXER, MSGL_DBG2, "n=%d, type=%c, temp_ref=%u\n", n, FTYPE(vpriv->framebuf[n].type), vpriv->framebuf[n].temp_ref);
mp_msg(MSGT_MUXER, MSGL_DBG2, "n=%d, type=%c\n", n, FTYPE(vpriv->framebuf[n].type));
if(n+1 < vpriv->framebuf_used)
mp_msg(MSGT_MUXER, MSGL_DBG2, "n+1=%d, type=%c, temp_ref=%u\n", n+1, FTYPE(vpriv->framebuf[n+1].type), vpriv->framebuf[n+1].temp_ref);
mp_msg(MSGT_MUXER, MSGL_DBG2, "n+1=%d, type=%c\n", n+1, FTYPE(vpriv->framebuf[n+1].type));
if(vpriv->framebuf[n].type == I_FRAME)
{
@ -1255,123 +1198,6 @@ static int calc_frames_to_flush(muxer_headers_t *vpriv)
}
static uint64_t fix_pts(muxer_priv_t *priv, muxer_headers_t *vpriv, int n)
{
int i, j, fixed = 0;
uint64_t last_dts, last_idur, ret;
uint32_t mintr, maxtr;
ret = 0;
if((vpriv->size == 0) && (fixed == 0)) //first pts adjustment, only at the beginning of the stream to manage BBI structures
{
int delay = 0;
for(i = 0; i < n; i++)
{
if(vpriv->framebuf[i].type == I_FRAME)
{
for(j = i + 1; j < n; j++)
{
if(vpriv->framebuf[i].temp_ref >= vpriv->framebuf[j].temp_ref)
{
ret += vpriv->framebuf[j].idur;
delay++;
fixed = 1;
}
}
if(fixed)
break;
}
}
if(! fixed)
ret = 0;
else
vpriv->last_pts += ret;
mp_msg(MSGT_MUXER, MSGL_INFO, "INITIAL DELAY of %d frames\n", delay);
}
//KLUDGE BEGINS: Gop header (0x000001b8 in the video stream that signals a temp_ref wraparound) is _not_ mandatory,
//so if we don't detect the right wraparound we will have a totally wrong timestamps assignment; let's go on
mintr = vpriv->framebuf[0].temp_ref;
maxtr = vpriv->framebuf[0].temp_ref;
for(i = 0; i < n; i++)
{
mintr = min(vpriv->framebuf[i].temp_ref, mintr);
maxtr = max(vpriv->framebuf[i].temp_ref, maxtr);
}
if(maxtr - mintr > 600) //there must be a temp_ref wraparound
{
mp_msg(MSGT_MUXER, MSGL_V, "\nDETECTED possible temp_ref wraparound in the videostreams: n=%d, mintr=%u, maxtr=%u\n", n, mintr, maxtr);
for(i = 0; i < n; i++)
{
if(vpriv->framebuf[i].temp_ref < 1000)
vpriv->framebuf[i].temp_ref += 1024;
}
}
//KLUDGE ENDS
for(i = 0; i < n; i++)
{
vpriv->framebuf[i].pts = vpriv->last_pts;
for(j = 0; j < n; j++)
{
if((vpriv->framebuf[i].temp_ref >= vpriv->framebuf[j].temp_ref) && (i != j))
{
vpriv->framebuf[i].pts += vpriv->framebuf[j].idur;
}
}
}
if(vpriv->size == 0)
last_dts = vpriv->init_dts = vpriv->framebuf[0].pts - (ret + vpriv->framebuf[0].idur);
else
last_dts = vpriv->last_dts;
last_idur = 0;
mp_msg(MSGT_MUXER, MSGL_DBG2, "\n");
for(i = 0; i < n; i++)
{
vpriv->framebuf[i].dts = last_dts + last_idur;
last_idur = vpriv->framebuf[i].idur;
last_dts = vpriv->framebuf[i].dts;
mp_msg(MSGT_MUXER, MSGL_DBG2, "I=%d, type: %c, TR: %u, pts=%.3lf, dts=%.3lf, size=%u\n",
i, FTYPE(vpriv->framebuf[i].type), vpriv->framebuf[i].temp_ref, (double) (vpriv->framebuf[i].pts/27000000.0),
(double) (vpriv->framebuf[i].dts/27000000.0), vpriv->framebuf[i].size);
}
if((vpriv->size == 0) && (priv->init_delay_pts > 0))
{
uint64_t diff;
for(i = 0; i < vpriv->framebuf_used; i++)
{
vpriv->framebuf[i].pts += priv->init_delay_pts;
vpriv->framebuf[i].dts += priv->init_delay_pts;
}
diff = vpriv->framebuf[0].pts - vpriv->framebuf[0].dts;
if(vpriv->init_pts >= diff)
vpriv->init_dts = vpriv->init_pts - diff;
else
vpriv->init_dts = diff;
vpriv->last_dts += priv->init_delay_pts;
vpriv->init_pts = 0;
vpriv->last_pts += priv->init_delay_pts;
priv->init_delay_pts = 0;
mp_msg(MSGT_MUXER, MSGL_INFO, "INIT delayed video timestamps: PTS=%.3lf, DTS=%.3lf, DUR=%.3lf\n",
(double) (vpriv->last_pts/27000000.0), (double) (vpriv->last_dts/27000000.0), (double) (vpriv->framebuf[0].idur/27000000.0));
}
return ret;
}
static void check_pts(muxer_priv_t *priv, muxer_headers_t *vpriv, int i)
{
@ -1481,6 +1307,8 @@ init:
{
vs = muxer->streams[i];
vpriv = (muxer_headers_t*) vs->priv;
if(!vpriv->is_ready)
return 0;
n = found = calc_frames_to_flush(vpriv);
}
else if(s->type == MUXER_TYPE_AUDIO)
@ -1510,10 +1338,7 @@ init:
}
duration = (double) (iduration / 27000000.0);
if(vpriv->is_mpeg12)
init_delay = fix_pts(priv, vpriv, n);
else
init_delay = 0;
init_delay = 0;
if(as != NULL)
{
@ -1555,7 +1380,7 @@ init:
idur = 0;
offset = 0;
priv->scr = vpriv->framebuf[0].dts - vpriv->init_dts;
priv->scr = vpriv->framebuf[0].dts - vpriv->framebuf[0].idur;
if((priv->is_xvcd || priv->is_xsvcd) && (vpriv->size == 0))
vpriv->buffer_size = (priv->is_xvcd ? 46 : 230)*1024;
@ -1567,9 +1392,6 @@ init:
uint32_t pl_size = 0, target_size;
uint8_t *buf;
mp_msg(MSGT_MUXER, MSGL_DBG2, "FRAME: %d, type: %c, TEMP_REF: %u, SIZE: %u\n",
i, FTYPE(vpriv->framebuf[i].type), vpriv->framebuf[i].temp_ref, vpriv->framebuf[i].size);
vpriv->pts = vpriv->framebuf[i].pts;
vpriv->dts = vpriv->framebuf[i].dts;
check_pts(priv, vpriv, i);
@ -1876,6 +1698,7 @@ static size_t parse_mpeg12_video(muxer_stream_t *s, muxer_priv_t *priv, muxer_he
uint8_t *se_ptr = NULL; //pointer to sequence extension
uint8_t *pce_ptr = NULL; //pointer to picture coding extension
int frames_diff, d1, gop_reset = 0; //how any frames we advanced respect to the last one
int ret;
mp_msg(MSGT_MUXER, MSGL_DBG2,"parse_mpeg12_video, len=%u\n", (uint32_t) len);
if(s->buffer[0] != 0 || s->buffer[1] != 0 || s->buffer[2] != 1 || len<6)
@ -1959,7 +1782,8 @@ static size_t parse_mpeg12_video(muxer_stream_t *s, muxer_priv_t *priv, muxer_he
}
else
{
if(!spriv->nom_delta_pts) //workaround: lavf doesn't sync to sequence headers before passing demux_packets
//following 2 lines are workaround: lavf doesn't sync to sequence headers before passing demux_packets
if(!spriv->nom_delta_pts)
spriv->delta_pts = spriv->nom_delta_pts = parse_fps(fps);
pt = (s->buffer[ptr+5] & 0x1c) >> 3;
temp_ref = (s->buffer[ptr+4]<<2)+(s->buffer[ptr+5]>>6);
@ -1976,18 +1800,18 @@ static size_t parse_mpeg12_video(muxer_stream_t *s, muxer_priv_t *priv, muxer_he
frames_diff = spriv->max_tr + 1 + temp_ref - spriv->last_tr;
else if(d1 > 6) //there's a wraparound
frames_diff = spriv->max_tr + 1 + spriv->last_tr - temp_ref;
else
else if(!d1) //pre-emptive fix against broken sequences
frames_diff = 1;
else
frames_diff = d1;
}
mp_msg(MSGT_MUXER, MSGL_DBG2, "\nLAST: %d, TR: %d, GOP: %d, DIFF: %d, MAX: %d, d1: %d\n",
spriv->last_tr, temp_ref, gop_reset, frames_diff, spriv->max_tr, d1);
if(!temp_ref)
spriv->max_tr = 0;
else if(temp_ref > spriv->max_tr)
if(temp_ref > spriv->max_tr || gop_reset)
spriv->max_tr = temp_ref;
spriv->last_tr = temp_ref;
mp_msg(MSGT_MUXER, MSGL_DBG2, "Video frame type: %c, TR: %d\n", FTYPE(pt), temp_ref);
if(spriv->picture.mpeg1 == 0)
{
size_t tmp = ptr;
@ -2000,6 +1824,7 @@ static size_t parse_mpeg12_video(muxer_stream_t *s, muxer_priv_t *priv, muxer_he
pce_ptr = &(s->buffer[ptr+4]);
if(spriv->telecine)
soft_telecine(spriv, fps_ptr, se_ptr, pce_ptr, frames_diff);
spriv->picture.display_time = 100;
mp_header_process_extension(&(spriv->picture), &(s->buffer[ptr+4]));
if(spriv->picture.display_time >= 50 && spriv->picture.display_time <= 300)
spriv->delta_pts = (spriv->nom_delta_pts * spriv->picture.display_time) / 100;
@ -2010,9 +1835,46 @@ static size_t parse_mpeg12_video(muxer_stream_t *s, muxer_priv_t *priv, muxer_he
ptr = tmp;
}
}
if(! spriv->vframes)
frames_diff = 1;
spriv->last_dts += spriv->delta_pts;
spriv->last_pts += spriv->nom_delta_pts*(frames_diff-1) + spriv->delta_pts;
ret = add_frame(spriv, spriv->delta_pts, s->buffer, len, pt, spriv->last_dts, spriv->last_pts);
if(ret < 0)
{
mp_msg(MSGT_MUXER, MSGL_FATAL, "\r\nPARSE_MPEG12: add_frames(%d) failed, exit\r\n", len);
return 0;
}
mp_msg(MSGT_MUXER, MSGL_DBG2, "\r\nVIDEO FRAME, PT: %C, tr: %d, diff: %d, dts: %.3lf, pts: %.3lf, pdt: %u, gop_reset: %d\r\n",
ftypes[pt], temp_ref, frames_diff, ((double) spriv->last_dts/27000000.0f),
((double) spriv->last_pts/27000000.0f), spriv->picture.display_time, gop_reset);
if(pt == B_FRAME)
{
int j, n, adj = 0;
int64_t diff = spriv->last_dts - spriv->last_pts;
if(diff != 0)
{
n = spriv->framebuf_used - 1;
for(j = n; j >= 0; j--)
{
if(spriv->framebuf[j].pts >= spriv->last_pts)
{
spriv->framebuf[j].pts += diff;
adj++;
}
}
mp_msg(MSGT_MUXER, MSGL_V, "\r\nResynced B-frame by %d units, DIFF: %lld (%.3lf),[pd]ts=%.3lf\r\n",
n, diff, (double) diff/27000000.0f, (double) spriv->last_pts/27000000.0f);
spriv->last_pts = spriv->last_dts;
}
}
spriv->vframes++;
add_frame(spriv, spriv->delta_pts, s->buffer, len, pt, temp_ref);
}
mp_msg(MSGT_MUXER, MSGL_DBG2,"parse_mpeg12_video, return %u\n", (uint32_t) len);
@ -2040,13 +1902,13 @@ static uint64_t fix_mp4_frame_duration(muxer_headers_t *vpriv)
if((vpriv->framebuf[i].pts > mn) && (vpriv->framebuf[i].pts < mx))
md = vpriv->framebuf[i].pts;
}
mp_msg(MSGT_DECVIDEO,MSGL_DBG2, "MIN: %"PRIu64", mid: %"PRIu64", max: %"PRIu64"\n", mn, md, mx);
if(mx - md > md - mn)
diff = md - mn;
else
diff = mx - md;
mp_msg(MSGT_DECVIDEO,MSGL_DBG2, "MIN: %"PRIu64", mid: %"PRIu64", max: %"PRIu64", diff: %"PRIu64"\n", mn, md, mx, diff);
if(diff > 0)
{
for(i=0; i<3; i++)
@ -2068,6 +1930,7 @@ static size_t parse_mpeg4_video(muxer_stream_t *s, muxer_priv_t *priv, muxer_hea
size_t ptr = 0;
int64_t delta_pts=0;
uint8_t pt;
int ret;
mp_msg(MSGT_MUXER, MSGL_DBG2,"parse_mpeg4_video, len=%u\n", (uint32_t) len);
if(len<6)
@ -2076,6 +1939,7 @@ static size_t parse_mpeg4_video(muxer_stream_t *s, muxer_priv_t *priv, muxer_hea
return 0;
}
pt = 0;
while(ptr < len - 5)
{
if(s->buffer[ptr] != 0 || s->buffer[ptr+1] != 0 || s->buffer[ptr+2] != 1)
@ -2104,6 +1968,7 @@ static size_t parse_mpeg4_video(muxer_stream_t *s, muxer_priv_t *priv, muxer_hea
delta += vpriv->picture.timeinc_resolution;
delta_pts = (27000000 * (int64_t) delta) / vpriv->picture.timeinc_resolution;
//warning, it seems that packed bops can lead to delta == 0
pt = vpriv->picture.picture_type + 1;
mp_msg(MSGT_MUXER, MSGL_DBG2, "\nTYPE: %c, RESOLUTION: %d, TEMP: %d, delta: %d, delta_pts: %"PRId64" = %.3lf, delta2: %.3lf\n",
@ -2118,18 +1983,18 @@ static size_t parse_mpeg4_video(muxer_stream_t *s, muxer_priv_t *priv, muxer_hea
ptr++;
}
vpriv->last_dts += vpriv->frame_duration;
vpriv->last_pts += delta_pts;
if(vpriv->vframes)
{
vpriv->last_dts += vpriv->frame_duration;
vpriv->last_pts += delta_pts;
}
add_frame(vpriv, delta_pts, s->buffer, len, pt, 0);
vpriv->framebuf[vpriv->framebuf_used-1].pts = vpriv->last_pts;
vpriv->framebuf[vpriv->framebuf_used-1].dts = vpriv->last_dts;
vpriv->framebuf[vpriv->framebuf_used-1].idur = vpriv->frame_duration;
/*mp_msg(MSGT_MUXER, MSGL_DBG2, "\nMPEG4V, PT: %c, LEN=%u, DELTA_PTS: %.3lf, PTS: %.3lf, DTS: %.3lf\n",
FTYPE(pt), len, (delta_pts/27000000.0),
(double) (vpriv->framebuf[vpriv->framebuf_used-1].pts/27000000.0),
(double) (vpriv->framebuf[vpriv->framebuf_used-1].dts/27000000.0), len);*/
ret = add_frame(vpriv, delta_pts, s->buffer, len, pt, vpriv->last_dts, vpriv->last_pts);
if(ret < 0)
{
mp_msg(MSGT_MUXER, MSGL_FATAL, "\r\nPARSE_MPEG12: add_frames(%d) failed, exit\r\n", len);
return 0;
}
if(!vpriv->frame_duration && vpriv->framebuf_used == 3)
{
@ -2141,11 +2006,14 @@ static size_t parse_mpeg4_video(muxer_stream_t *s, muxer_priv_t *priv, muxer_hea
vpriv->delta_clock = ((double) vpriv->frame_duration)/27000000.0;
mp_msg(MSGT_MUXER, MSGL_INFO, "FRAME DURATION: %"PRIu64" %.3lf\n",
vpriv->frame_duration, (double) (vpriv->frame_duration/27000000.0));
vpriv->is_ready = 1;
}
}
mp_msg(MSGT_MUXER, MSGL_DBG2, "LAST_PTS: %.3lf, LAST_DTS: %.3lf\n",
(double) (vpriv->last_pts/27000000.0), (double) (vpriv->last_dts/27000000.0));
vpriv->vframes++;
return len;
}
@ -2177,9 +2045,9 @@ static int fill_last_frame(muxer_headers_t *spriv, uint8_t *ptr, int len)
return len;
}
static int add_frame(muxer_headers_t *spriv, uint64_t idur, uint8_t *ptr, int len, uint8_t pt, uint32_t temp_ref)
static int add_frame(muxer_headers_t *spriv, uint64_t idur, uint8_t *ptr, int len, uint8_t pt, uint64_t dts, uint64_t pts)
{
int idx, i;
int idx;
idx = spriv->framebuf_used;
if(idx >= spriv->framebuf_cnt)
@ -2219,11 +2087,13 @@ static int add_frame(muxer_headers_t *spriv, uint64_t idur, uint8_t *ptr, int le
memcpy(&(spriv->framebuf[idx].buffer[spriv->framebuf[idx].size]), ptr, len);
spriv->framebuf[idx].size += len;
spriv->framebuf[idx].pos = 0;
spriv->framebuf[idx].temp_ref = temp_ref;
spriv->framebuf[idx].type = pt;
spriv->framebuf[idx].idur = idur;
spriv->framebuf[idx].dts = dts;
spriv->framebuf[idx].pts = pts;
spriv->framebuf_used++;
mp_msg(MSGT_MUXER, MSGL_DBG2, "\r\nAdded frame, size: %u, idur: %llu, dts: %llu, pts: %llu, used: %u\r\n", len, idur, dts, pts, spriv->framebuf_used);
return idx;
}
@ -2231,10 +2101,12 @@ static int add_frame(muxer_headers_t *spriv, uint64_t idur, uint8_t *ptr, int le
extern int aac_parse_frame(uint8_t *buf, int *srate, int *num);
static int parse_audio(muxer_stream_t *s, int finalize, int *nf, double *timer)
static int parse_audio(muxer_stream_t *s, int finalize, unsigned int *nf, double *timer, double delay, int drop)
{
int i, j, len, chans, srate, spf, layer, dummy, tot, num, frames, frm_idx;
int i, j, len, chans, srate, spf, layer, dummy, tot, num, frm_idx;
unsigned int frames;
uint64_t idur;
double dur;
muxer_headers_t *spriv = (muxer_headers_t *) s->priv;
i = tot = frames = 0;
@ -2250,11 +2122,19 @@ static int parse_audio(muxer_stream_t *s, int finalize, int *nf, double *timer)
len = mp_get_mp3_header(&(s->b_buffer[i]), &chans, &srate, &spf, &layer, NULL);
if(len > 0 && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len))
{
dur = (double) spf / (double) srate;
spriv->timer += dur;
if(spriv->drop_delayed_frames && delay < 0 && spriv->timer <= -delay)
{
i += len;
tot = i;
continue;
}
frames++;
fill_last_frame(spriv, &(s->b_buffer[tot]), i - tot);
idur = (27000000ULL * spf) / srate;
frm_idx = add_frame(spriv, idur, &(s->b_buffer[i]), len, 0, 0);
frm_idx = add_frame(spriv, idur, &(s->b_buffer[i]), len, 0, spriv->last_pts, spriv->last_pts);
if(frm_idx < 0)
continue;
for(j = frm_idx; j < spriv->framebuf_cnt; j++)
@ -2285,11 +2165,19 @@ static int parse_audio(muxer_stream_t *s, int finalize, int *nf, double *timer)
#endif
if((len > 0) && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len))
{
dur = (double) 1536 / (double) srate;
spriv->timer += dur;
if(spriv->drop_delayed_frames && delay < 0 && spriv->timer <= -delay)
{
i += len;
tot = i;
continue;
}
frames++;
fill_last_frame(spriv, &(s->b_buffer[tot]), i - tot);
idur = (27000000ULL * 1536) / srate;
frm_idx = add_frame(spriv, idur, &(s->b_buffer[i]), len, 0, 0);
frm_idx = add_frame(spriv, idur, &(s->b_buffer[i]), len, 0, spriv->last_pts, spriv->last_pts);
if(frm_idx < 0)
continue;
for(j = frm_idx; j < spriv->framebuf_cnt; j++)
@ -2316,11 +2204,19 @@ static int parse_audio(muxer_stream_t *s, int finalize, int *nf, double *timer)
len = aac_parse_frame(&(s->b_buffer[i]), &srate, &num);
if((len > 0) && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len))
{
dur = (double) 1024 / (double) srate;
spriv->timer += dur;
if(spriv->drop_delayed_frames && delay < 0 && spriv->timer <= -delay)
{
i += len;
tot = i;
continue;
}
frames++;
fill_last_frame(spriv, &(s->b_buffer[tot]), i - tot);
idur = (27000000ULL * 1024 * num) / srate;
frm_idx = add_frame(spriv, idur, &(s->b_buffer[i]), len, 0, 0);
frm_idx = add_frame(spriv, idur, &(s->b_buffer[i]), len, 0, spriv->last_pts, spriv->last_pts);
if(frm_idx < 0)
continue;
for(j = frm_idx; j < spriv->framebuf_cnt; j++)
@ -2349,7 +2245,7 @@ static int parse_audio(muxer_stream_t *s, int finalize, int *nf, double *timer)
if(finalize)
{
frm_idx = add_frame(spriv, 0, s->b_buffer, s->b_buffer_len, 0, 0);
frm_idx = add_frame(spriv, 0, s->b_buffer, s->b_buffer_len, 0, spriv->last_pts, spriv->last_pts);
if(frm_idx >= 0)
{
for(j = frm_idx; j < spriv->framebuf_cnt; j++)
@ -2358,7 +2254,7 @@ static int parse_audio(muxer_stream_t *s, int finalize, int *nf, double *timer)
}
*nf = frames;
*timer = (double) (spriv->last_pts - spriv->init_pts)/27000000.0;
*timer = spriv->timer;
return tot;
}
@ -2388,14 +2284,20 @@ static void mpegfile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags
spriv->type = 1;
spriv->has_pes_priv_headers = 0;
stream_format = s->bih->biCompression;
if(! spriv->vframes)
{
spriv->last_dts = spriv->last_pts - (uint64_t)(27000000.0f/fps);
mp_msg(MSGT_MUXER, MSGL_INFO,"INITV: %.3lf, %.3lf, fps: %.3f\r\n", (double) spriv->last_pts/27000000.0f, (double) spriv->last_dts/27000000.0f, fps);
}
if(is_mpeg1(stream_format) || is_mpeg2(stream_format))
{
spriv->is_mpeg12 = 1;
spriv->is_ready = 1;
if(len)
sz = parse_mpeg12_video(s, priv, spriv, fps, len);
else {
tmp = (uint64_t) (27000000 / fps);
tmp = (uint64_t) (27000000.0f / fps);
spriv->last_pts += tmp;
spriv->last_dts += tmp;
}
@ -2409,7 +2311,7 @@ static void mpegfile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags
if(len)
sz = parse_mpeg4_video(s, priv, spriv, fps, len);
else {
tmp = (uint64_t) (27000000 / fps);
tmp = (uint64_t) (27000000.0f / fps);
spriv->last_pts += tmp;
spriv->last_dts += tmp;
}
@ -2419,18 +2321,13 @@ static void mpegfile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags
ptr = 0;
priv->vbytes += len;
sz <<= 1;
} else { // MUXER_TYPE_AUDIO
double fake_timer;
spriv->type = 0;
stream_format = s->wf->wFormatTag;
mp_msg(MSGT_MUXER, MSGL_DBG2,"\nmpegfile_write_chunk, Audio codec=%x, len=%u, frame size=%u\n",
stream_format, (uint32_t) len, (uint32_t) spriv->frame_size);
if(spriv->bitrate == 0)
spriv->bitrate = s->wf->nAvgBytesPerSec;
if(! spriv->vframes)
mp_msg(MSGT_MUXER, MSGL_INFO, "AINIT: %.3lf\r\n", (double) spriv->last_pts/27000000.0f);
if(s->b_buffer_size - s->b_buffer_len < len)
{
s->b_buffer = realloc(s->b_buffer, len + s->b_buffer_len);
@ -2464,30 +2361,8 @@ static void mpegfile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags
priv->use_psm = 1;
}
if(priv->init_adelay < 0)
{
uint64_t delay_len;
priv->abytes += len;
delay_len = (uint64_t) abs((priv->init_adelay * (double) spriv->bitrate));
if(priv->abytes >= delay_len)
{
if(priv->drop)
{
mp_msg(MSGT_MUXER, MSGL_V, "\nDROPPING %"PRIu64" AUDIO BYTES, DELAY: %.3lf, BR: %u\n", delay_len, priv->init_adelay, spriv->bitrate);
drop_delayed_audio(muxer, s, (int64_t) delay_len);
}
else
{
mp_msg(MSGT_MUXER, MSGL_V, "\nWRITING %"PRIu64" EARLY AUDIO BYTES, DELAY: %.3lf, BR: %u\n", delay_len, priv->init_adelay, spriv->bitrate);
save_delayed_audio(muxer, s, (uint64_t) (27000000 * (-priv->init_adelay)));
}
priv->init_adelay = 0.0;
conf_init_adelay = 0;
priv->drop = 0;
}
}
parse_audio(s, 0, &nf, &fake_timer);
parse_audio(s, 0, &nf, &fake_timer, priv->init_adelay, priv->drop);
spriv->vframes += nf;
sz = max(len, 2 * priv->packet_size);
}
@ -2519,7 +2394,7 @@ static void mpegfile_write_index(muxer_t *muxer)
for(i = 0; i < muxer->avih.dwStreams; i++)
{
if(muxer->streams[i]->type == MUXER_TYPE_AUDIO)
parse_audio(muxer->streams[i], 1, &nf, &fake_timer);
parse_audio(muxer->streams[i], 1, &nf, &fake_timer, priv->init_adelay, priv->drop);
}
while(flush_buffers(muxer, 0) > 0);
flush_buffers(muxer, 1);