summaryrefslogtreecommitdiffstats
path: root/libmpdemux/muxer_mpeg.c
diff options
context:
space:
mode:
authornicodvb <nicodvb@b3059339-0415-0410-9bf9-f77b7e298cf2>2005-07-10 08:36:39 +0000
committernicodvb <nicodvb@b3059339-0415-0410-9bf9-f77b7e298cf2>2005-07-10 08:36:39 +0000
commit57f50fad9e6f28d026fcdb79999d117d976a65fa (patch)
treed50df1bf58cc8bf91f7080a80f7d6a5786188532 /libmpdemux/muxer_mpeg.c
parent8c6cf5151057da4e2201c6f4e464ab8b31aa25ad (diff)
downloadmpv-57f50fad9e6f28d026fcdb79999d117d976a65fa.tar.bz2
mpv-57f50fad9e6f28d026fcdb79999d117d976a65fa.tar.xz
added support for vbr audio (frames are parsed individually); fixed small bugs in the management of pes_extension
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@15948 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libmpdemux/muxer_mpeg.c')
-rw-r--r--libmpdemux/muxer_mpeg.c461
1 files changed, 349 insertions, 112 deletions
diff --git a/libmpdemux/muxer_mpeg.c b/libmpdemux/muxer_mpeg.c
index 96c448e776..5d1fedc98a 100644
--- a/libmpdemux/muxer_mpeg.c
+++ b/libmpdemux/muxer_mpeg.c
@@ -94,6 +94,7 @@ typedef struct {
uint8_t type;
uint32_t temp_ref;
uint64_t pts, dts, idur;
+ uint32_t pos; //start offset for the frame
} mpeg_frame_t;
typedef struct {
@@ -126,7 +127,7 @@ typedef struct {
off_t headers_size, data_size;
uint64_t scr, vbytes, abytes, init_delay_pts;
uint32_t muxrate;
- uint8_t *buff, *tmp, *residual;
+ uint8_t *buff, *tmp, *abuf, *residual;
uint32_t residual_cnt, headers_cnt;
double init_adelay;
int drop;
@@ -412,6 +413,7 @@ static muxer_stream_t* mpegfile_new_stream(muxer_t *muxer,int type){
spriv->max_pl_size = priv->packet_size - calc_pack_hlen(priv, spriv);
spriv->init_pts = conf_init_apts * 90 * 1024;
spriv->pts = spriv->init_pts;
+ spriv->last_pts = spriv->init_pts;
spriv->dts = 0;
spriv->id = 0xc0 + muxer->num_audios;
s->ckid = be2me_32 (0x100 + spriv->id);
@@ -431,6 +433,15 @@ static muxer_stream_t* mpegfile_new_stream(muxer_t *muxer,int type){
muxer->num_audios++;
priv->has_audio++;
s->h.fccType=streamtypeAUDIO;
+
+ spriv->framebuf_cnt = 30;
+ spriv->framebuf_used = 0;
+ spriv->framebuf = init_frames(spriv->framebuf_cnt, (size_t) 2048);
+ if(spriv->framebuf == NULL) {
+ mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't allocate initial frames structure, abort!\n");
+ return NULL;
+ }
+
mp_msg (MSGT_MUXER, MSGL_DBG2, "Added audio stream %d, ckid=%X\n", s->id - muxer->num_videos + 1, s->ckid);
}
muxer->avih.dwStreams++;
@@ -671,7 +682,7 @@ static int write_mpeg_pes_header(muxer_headers_t *h, uint8_t *pes_id, uint8_t *b
{
if(h->buffer_size > 0)
{
- buff[len] = 0x10; //std flag
+ buff[len] = 0x1e; //std flag
len++;
write_mpeg_std(&buff[len], h->buffer_size, h->type, 0x40);
@@ -757,7 +768,7 @@ static uint32_t calc_pes_hlen(int format, muxer_headers_t *h, muxer_priv_t *priv
if(format == MUX_MPEG1)
len = 6;
else
- len = 9; //era 12
+ len = 9;
if(h->pts)
{
@@ -783,7 +794,7 @@ static uint32_t calc_pes_hlen(int format, muxer_headers_t *h, muxer_priv_t *priv
static uint32_t calc_pack_hlen(muxer_priv_t *priv, muxer_headers_t *h)
{
- uint32_t len;
+ uint32_t len, x;
if(priv->mux == MUX_MPEG1)
len = 12;
@@ -793,10 +804,11 @@ static uint32_t calc_pack_hlen(muxer_priv_t *priv, muxer_headers_t *h)
/*if((priv->is_genmpeg1 || priv->is_genmpeg2) && priv->update_system_header)
len += (6 + (3*priv->sys_info.cnt));*/
- if(h->min_pes_hlen > 0)
+ x = calc_pes_hlen(priv->mux, h, priv);
+ if(h->min_pes_hlen > x)
len += h->min_pes_hlen;
else
- len += calc_pes_hlen(priv->mux, h, priv);
+ len += x;
return len;
}
@@ -1002,38 +1014,6 @@ static void patch_panscan(muxer_priv_t *priv, unsigned char *buf)
#define min(a, b) ((a) <= (b) ? (a) : (b))
-static uint32_t get_audio_frame_size(muxer_headers_t *spriv, uint8_t *buf, int format, int samples_ps)
-{
- uint32_t sz, tmp, spf;
-
-#ifdef USE_LIBA52
-#include "../liba52/a52.h"
- if(format == 0x2000)
- {
- int t1, t2, t3;
- sz = (uint32_t) a52_syncinfo(buf, &t1, &t2, &t3);
- if(sz)
- return sz;
- }
-#endif
- if(format == 0x2000)
- spf = 1536;
- else if(format == AUDIO_AAC1 || format == AUDIO_AAC2)
- spf = 1024;
- else if((format == 0x55) && (samples_ps < 32000))
- spf = 576;
- else
- spf = 1152;
-
- tmp = spriv->bitrate * spf;
- sz = tmp / samples_ps;
- if(sz % 2)
- sz++;
-
- return sz;
-}
-
-
static int reorder_frame(muxer_headers_t *spriv, uint8_t *ptr, size_t len, uint8_t pt, uint32_t temp_ref, uint64_t idur)
{
uint16_t idx = 0, move=0;
@@ -1064,7 +1044,6 @@ static int reorder_frame(muxer_headers_t *spriv, uint8_t *ptr, size_t len, uint8
//now idx is the position where we should store the frame
if(idx+move >= spriv->framebuf_cnt)
{ //realloc
- //fprintf(stderr, "\nREALLOC1: %d\n", (int) spriv->framebuf_cnt+1);
spriv->framebuf = (mpeg_frame_t*) realloc(spriv->framebuf, (spriv->framebuf_cnt+1)*sizeof(mpeg_frame_t));
if(spriv->framebuf == NULL)
{
@@ -1124,23 +1103,21 @@ static int reorder_frame(muxer_headers_t *spriv, uint8_t *ptr, size_t len, uint8
static uint32_t dump_audio(muxer_t *muxer, muxer_stream_t *as, uint32_t abytes, int force)
{
- uint32_t len = 0, sz;
+ uint32_t len = 0, tlen, sz;
uint64_t num_frames = 0, next_pts;
uint16_t rest;
int64_t tmp;
double delta_pts;
muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
muxer_headers_t *apriv = (muxer_headers_t*) as->priv;
-
- if((abytes < apriv->frame_size) && (! force)) //pl_size
- //if((abytes < apriv->max_pl_size) && (! force)) //pl_size
- {
- apriv->is_late = 1;
- mp_msg(MSGT_MUXER, MSGL_DBG2, "NOT SAVING: %u bytes\n", abytes);
- return 0;
- }
-
- abytes = min(abytes, as->b_buffer_len); //available bytes
+ uint32_t num, den, j, k, l, n;
+ mpeg_frame_t *frm , frm2;
+
+ tlen = 0;
+ for(j = 0; j < apriv->framebuf_used; j++)
+ tlen += apriv->framebuf[j].size - apriv->framebuf[j].pos;
+
+ abytes = min(abytes, tlen); //available bytes
if(! abytes)
return 0;
@@ -1149,23 +1126,85 @@ static uint32_t dump_audio(muxer_t *muxer, muxer_stream_t *as, uint32_t abytes,
else
apriv->has_pes_priv_headers = 0;
- rest = (apriv->size % apriv->frame_size);
- if(rest)
- rest = apriv->frame_size - rest;
-
+ rest = apriv->framebuf[0].pos;
sz = priv->packet_size - calc_pack_hlen(priv, apriv); //how many payload bytes we are about to write
- num_frames = (sz + apriv->frame_size - 1 - rest) / apriv->frame_size;
-
+ if(abytes < sz && !force)
+ return 0;
+ sz = min(sz, abytes);
+ num_frames = 0;
+ tlen = 0;
+ next_pts = 0;
+ for(j = 0; j < apriv->framebuf_used; j++)
+ {
+ frm = &(apriv->framebuf[j]);
+ k = min(frm->size - frm->pos, sz - tlen);
+ tlen += k;
+ if(!frm->pos)
+ num_frames++;
+ if(!frm->pos && !next_pts)
+ next_pts = frm->pts;
+ if(tlen == sz)
+ break;
+ }
+
+ if(tlen < sz && !force)
+ return 0;
+
+ if(!next_pts && force)
+ next_pts = apriv->last_pts;
+ apriv->last_dts = apriv->pts;
+ apriv->pts = next_pts;
mp_msg(MSGT_MUXER, MSGL_DBG2, "\nAUDIO: tot=%llu, sz=%u bytes, FRAMES: %llu * %u, REST: %u, DELTA_PTS: %u\n",
apriv->size, sz, num_frames, (uint32_t) apriv->frame_size, (uint32_t) rest, (uint32_t) ((num_frames * apriv->delta_pts) >> 10));
- next_pts = ((uint64_t) (num_frames * apriv->delta_pts)) + apriv->pts;
if(((priv->scr + (63000*1024)) < next_pts) && (priv->scr < apriv->pts) && (! force))
{
apriv->is_late = 1;
return 0;
}
+ n = 0; //number of complete frames
+ tlen = 0;
+ for(j = 0; j < apriv->framebuf_used; j++)
+ {
+ int frame_size;
+
+ frm = &(apriv->framebuf[j]);
+ frame_size = frm->size - frm->pos;
+ l = min(sz - tlen, frame_size);
+
+ memcpy(&(priv->abuf[tlen]), &(frm->buffer[frm->pos]), l);
+ tlen += l;
+ if(l < frame_size) //there are few bytes still to write
+ {
+ frm->pos += l;
+ break;
+ }
+ else
+ {
+ frm->pos = 0;
+ frm->size = 0;
+ n++;
+ }
+ }
+
+ if(num_frames)
+ apriv->frame_size = tlen/num_frames;
+ else
+ apriv->frame_size = tlen;
+
+ if(n)
+ {
+ for(j = n; j < apriv->framebuf_used; j++)
+ {
+ frm2 = apriv->framebuf[j - n];
+ apriv->framebuf[j - n] = apriv->framebuf[j];
+ apriv->framebuf[j] = frm2;
+ }
+ apriv->framebuf_used -= n;
+ }
+
+
if(as->ckid == be2me_32(0x1bd))
{
apriv->pes_priv_headers[0] = 0x80;
@@ -1176,43 +1215,37 @@ static uint32_t dump_audio(muxer_t *muxer, muxer_stream_t *as, uint32_t abytes,
if((priv->is_xsvcd || priv->is_xvcd) && apriv->size == 0)
apriv->buffer_size = 4*1024;
-
- if(apriv->pts < priv->scr)
- mp_msg(MSGT_MUXER, MSGL_ERR, "\nERROR: SCR: %llu, APTS: %llu, DELTA=-%.3lf secs\n",
- priv->scr, apriv->pts, (double) ((priv->scr - apriv->pts)/92160000.0));
- len = write_mpeg_pack(muxer, as, muxer->file, &(as->b_buffer[as->b_buffer_ptr]), abytes, 0);
+ len = write_mpeg_pack(muxer, as, muxer->file, priv->abuf, tlen, 0);
+
if((priv->is_xsvcd || priv->is_xvcd) && apriv->size == 0)
apriv->buffer_size = 0;
apriv->size += len;
- apriv->pts = next_pts;
-
- mp_msg(MSGT_MUXER, MSGL_DBG2, "NUM_FRAMES: %llu\n", num_frames);
tmp = apriv->pts - priv->scr;
if((abs(tmp) > (63000*1024)) || (apriv->pts <= priv->scr))
{
double d;
- d = (double) apriv->frame_size / (double) apriv->bitrate;
- d *= (tmp - (63000*1024));
- apriv->compensate = (uint32_t) d;
+
+ if(tmp > 0)
+ tmp = tmp - (63000*1024);
+
+ d = -tmp / 92160000.0;
+ d *= apriv->bitrate;
+ apriv->compensate = (int32_t) d;
- if(abs(tmp) > 92160000) //usually up to 1 second it still acceptable
- mp_msg(MSGT_MUXER, MSGL_ERR, "\nWARNING: SCR: %llu, APTS: %llu, DELTA=%.3lf secs, BYTES=%d\n", priv->scr, apriv->pts,
- (((double) tmp)/92160000.0), apriv->compensate);
+ if((tmp) > 92160000) //usually up to 1 second it still acceptable
+ mp_msg(MSGT_MUXER, MSGL_ERR, "\nWARNING: SCR: << APTS, DELTA=%.3lf secs, COMPENSATE=%d, BR: %d\n",
+ (((double) tmp)/92160000.0), apriv->compensate, apriv->bitrate);
+ else if(apriv->pts < priv->scr)
+ mp_msg(MSGT_MUXER, MSGL_ERR, "\nERROR: SCR: %llu, APTS: %llu, DELTA=-%.3lf secs, COMPENSATE=%d, BR: %d, lens: %d/%d, frames: %d\n",
+ priv->scr, apriv->pts, (double) ((priv->scr - apriv->pts)/92160000.0), apriv->compensate, apriv->bitrate, tlen, len, n);
}
mp_msg(MSGT_MUXER, MSGL_DBG2, "\nWRITTEN AUDIO: %u bytes, TIMER: %.3lf, FRAMES: %llu * %u, DELTA_PTS: %.3lf\n",
len, (double) (apriv->pts/92160000), num_frames, (uint32_t) apriv->frame_size, delta_pts);
- as->b_buffer_ptr += len;
- as->b_buffer_len -= len;
-
- if(as->b_buffer_len > 0)
- memmove(as->b_buffer, &(as->b_buffer[as->b_buffer_ptr]), as->b_buffer_len);
- as->b_buffer_ptr = 0;
-
return len;
}
@@ -1238,6 +1271,7 @@ static void drop_delayed_audio(muxer_t *muxer, muxer_stream_t *as, int64_t size)
rest = size1 - size;
rest_pts = (double) rest / (double) apriv->bitrate;
apriv->pts += (int64_t) (92160000.0 * rest_pts);
+ apriv->last_pts += (int64_t) (92160000.0 * rest_pts);
mp_msg(MSGT_MUXER, MSGL_DBG2, "DROPPED: %lld bytes, REST= %lld, REST_PTS: %.3lf, AUDIO_PTS%.3lf\n", size1, rest, rest_pts, (double) (apriv->pts/92160000.0));
}
@@ -1468,18 +1502,30 @@ static void check_pts(muxer_priv_t *priv, muxer_headers_t *vpriv, int i)
static uint32_t calc_audio_chunk_size(muxer_stream_t *as, double duration, int finalize)
{
muxer_headers_t *apriv;
- uint32_t x, div, rest, abytes;
+ uint32_t x, div, rest, abytes, available;
double adur;
uint64_t iaduration;
+ int i;
apriv = (muxer_headers_t*) as->priv;
- abytes = (uint32_t) (duration * apriv->bitrate); //size of audio data to write
- x = (abytes + apriv->max_pl_size - 1) / apriv->max_pl_size;
- x *= apriv->max_pl_size;
- adur = (double) x / (double) apriv->bitrate;
- iaduration = (uint64_t) ((double) 92160000 * adur);
+
+ iaduration = 0;
+ adur = 0;
+ available = abytes = 0;
+ for(i = 0; i < apriv->framebuf_used; i++)
+ {
+ if(adur < duration)
+ abytes += apriv->framebuf[i].size - apriv->framebuf[i].pos;
+ adur += (double)(apriv->framebuf[i].idur/92160000.0);
+ available += apriv->framebuf[i].size - apriv->framebuf[i].pos;
+ }
+
+
+ if(adur < duration && !finalize)
+ return 0;
- abytes -= apriv->compensate;
+ if(abytes > apriv->compensate)
+ abytes -= apriv->compensate;
div = abytes / apriv->max_pl_size;
rest = abytes % apriv->max_pl_size;
if(apriv->compensate > 0)
@@ -1490,8 +1536,11 @@ static uint32_t calc_audio_chunk_size(muxer_stream_t *as, double duration, int f
abytes = apriv->max_pl_size * (rest ? div + 1 : div);
apriv->compensate = 0;
+ while(abytes > available)
+ abytes -= apriv->max_pl_size;
+
if(finalize)
- abytes = as->b_buffer_len;
+ abytes = available;
return abytes;
}
@@ -1579,17 +1628,23 @@ init:
if(as != NULL)
{
+ uint32_t available, i;
+
apriv = (muxer_headers_t*) as->priv;
abytes = calc_audio_chunk_size(as, duration, finalize);
+ if(! abytes)
+ return 0;
+ for(i = 0; i < apriv->framebuf_used; i++)
+ available += apriv->framebuf[i].size - apriv->framebuf[i].pos;
if((abytes / apriv->max_pl_size) > n)
audio_rest = (abytes - (apriv->max_pl_size * n)) / n;
else
audio_rest = 0;
-
- if(as->b_buffer_len < abytes)
+
+ if(available < abytes && !finalize)
{
- mp_msg(MSGT_MUXER, MSGL_DBG2, "Not enough audio data (%u < %u), exit\n", as->b_buffer_len, abytes);
+ mp_msg(MSGT_MUXER, MSGL_DBG2, "Not enough audio data (%u < %u), exit\n", available, abytes);
return 0;
}
}
@@ -2155,6 +2210,195 @@ static size_t parse_mpeg4_video(muxer_stream_t *s, muxer_priv_t *priv, muxer_hea
return len;
}
+
+static int fill_last_frame(muxer_headers_t *spriv, uint8_t *ptr, int len)
+{
+ int idx;
+
+ if(!len)
+ return 0;
+
+ if(spriv->framebuf_used == 0)
+ idx = spriv->framebuf_used;
+ else
+ idx = spriv->framebuf_used - 1;
+
+ if(spriv->framebuf[idx].alloc_size < spriv->framebuf[idx].size + len)
+ {
+ spriv->framebuf[idx].buffer = (uint8_t*) realloc(spriv->framebuf[idx].buffer, spriv->framebuf[idx].size + len);
+ if(! spriv->framebuf[idx].buffer)
+ return 0;
+ spriv->framebuf[idx].alloc_size = spriv->framebuf[idx].size + len;
+ }
+
+ memcpy(&(spriv->framebuf[idx].buffer[spriv->framebuf[idx].size]), ptr, len);
+ spriv->framebuf[idx].size += len;
+
+ return len;
+}
+
+
+static int add_audio_frame(muxer_headers_t *spriv, uint64_t idur, uint8_t *ptr, int len)
+{
+ int idx, i;
+
+ idx = spriv->framebuf_used;
+ if(idx >= spriv->framebuf_cnt)
+ {
+ spriv->framebuf = (mpeg_frame_t*) realloc(spriv->framebuf, (spriv->framebuf_cnt+1)*sizeof(mpeg_frame_t));
+ if(spriv->framebuf == NULL)
+ {
+ mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't realloc frame buffer(idx), abort\n");
+ return 0;
+ }
+
+ spriv->framebuf[spriv->framebuf_cnt].size = 0;
+ spriv->framebuf[spriv->framebuf_cnt].alloc_size = 0;
+ spriv->framebuf[spriv->framebuf_cnt].pos = 0;
+
+ spriv->framebuf[spriv->framebuf_cnt].buffer = (uint8_t*) malloc(len);
+ if(spriv->framebuf[spriv->framebuf_cnt].buffer == NULL)
+ {
+ mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't realloc frame buffer(frame), abort\n");
+ return 0;
+ }
+ spriv->framebuf[spriv->framebuf_cnt].alloc_size = len;
+ spriv->framebuf_cnt++;
+ }
+
+ if(spriv->framebuf[idx].alloc_size < spriv->framebuf[idx].size + len)
+ {
+ spriv->framebuf[idx].buffer = realloc(spriv->framebuf[idx].buffer, spriv->framebuf[idx].size + len);
+ if(spriv->framebuf[idx].buffer == NULL)
+ {
+ mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't realloc frame buffer(frame), abort\n");
+ return 0;
+ }
+ spriv->framebuf[idx].alloc_size = spriv->framebuf[idx].size + len;
+ }
+
+ memcpy(&(spriv->framebuf[idx].buffer[spriv->framebuf[idx].size]), ptr, len);
+ spriv->framebuf[idx].size += len;
+ spriv->framebuf[idx].pos = 0;
+
+ spriv->framebuf[idx].idur = idur;
+ spriv->framebuf[idx].pts = spriv->last_pts;
+ spriv->framebuf_used++;
+
+ for(i = idx; i < spriv->framebuf_cnt; i++)
+ spriv->framebuf[i].pts = spriv->last_pts;
+
+ spriv->last_pts += idur;
+
+ return 1;
+}
+
+
+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)
+{
+ int i, len, chans, srate, spf, layer, dummy, tot, num, frames;
+ uint64_t idur;
+ muxer_headers_t *spriv = (muxer_headers_t *) s->priv;
+
+ i = tot = frames = 0;
+ switch(s->wf->wFormatTag)
+ {
+ case AUDIO_MP2:
+ case AUDIO_MP3:
+ {
+ while(i + 3 < s->b_buffer_len)
+ {
+ if(s->b_buffer[i] == 0xFF && ((s->b_buffer[i+1] & 0xE0) == 0xE0))
+ {
+ len = mp_get_mp3_header(&(s->b_buffer[i]), &chans, &srate, &spf, &layer);
+ if(len > 0 && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len))
+ {
+ frames++;
+ fill_last_frame(spriv, &(s->b_buffer[tot]), i - tot);
+
+ idur = (92160000ULL * spf) / srate;
+ add_audio_frame(spriv, idur, &(s->b_buffer[i]), len);
+ i += len;
+ tot = i;
+ continue;
+ }
+ }
+ i++;
+ }
+ }
+ break;
+
+ case AUDIO_A52:
+ {
+ while(i + 6 < s->b_buffer_len)
+ {
+ if(s->b_buffer[i] == 0x0B && s->b_buffer[i+1] == 0x77)
+ {
+ len = a52_syncinfo(&(s->b_buffer[i]), &dummy, &srate, &dummy);
+ if((len > 0) && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len))
+ {
+ frames++;
+ fill_last_frame(spriv, &(s->b_buffer[tot]), i - tot);
+
+ idur = (92160000ULL * 1536) / srate;
+ add_audio_frame(spriv, idur, &(s->b_buffer[i]), len);
+ i += len;
+ tot = i;
+ continue;
+ }
+ }
+ i++;
+ }
+ }
+ break;
+
+ case AUDIO_AAC1:
+ case AUDIO_AAC2:
+ {
+ while(i + 7 < s->b_buffer_len)
+ {
+ if(s->b_buffer[i] == 0xFF && ((s->b_buffer[i+1] & 0xF6) == 0xF0))
+ {
+ len = aac_parse_frame(&(s->b_buffer[i]), &srate, &num);
+ if((len > 0) && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len))
+ {
+ frames++;
+ fill_last_frame(spriv, &(s->b_buffer[tot]), i - tot);
+
+ idur = (92160000ULL * 1024 * num) / srate;
+ add_audio_frame(spriv, idur, &(s->b_buffer[i]), len);
+ i += len;
+ tot = i;
+ continue;
+ }
+ }
+ i++;
+ }
+ }
+ }
+
+ if(tot)
+ {
+ memmove(s->b_buffer, &(s->b_buffer[tot]), s->b_buffer_len - tot);
+ s->b_buffer_len -= tot;
+ s->b_buffer_ptr += tot;
+ if(s->b_buffer_len > 0)
+ memmove(s->b_buffer, &(s->b_buffer[s->b_buffer_ptr]), s->b_buffer_len);
+ s->b_buffer_ptr = 0;
+ }
+
+ if(finalize)
+ add_audio_frame(spriv, 0, s->b_buffer, s->b_buffer_len);
+ *nf = frames;
+ *timer = (double) (spriv->last_pts - spriv->init_pts)/92160000.0;
+
+ return tot;
+}
+
+
+
static void mpegfile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags){
size_t ptr=0, sz = 0;
uint64_t pts, tmp;
@@ -2163,7 +2407,7 @@ static void mpegfile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags
muxer_headers_t *spriv = (muxer_headers_t*) s->priv;
FILE *f;
float fps;
- uint32_t stream_format;
+ uint32_t stream_format, nf;
f = muxer->file;
@@ -2210,6 +2454,9 @@ static void mpegfile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags
priv->vbytes += len;
sz <<= 1;
+ s->h.dwLength++;
+ s->size += len;
+ s->timer = (double)s->h.dwLength*s->h.dwScale/s->h.dwRate;
} else { // MUXER_TYPE_AUDIO
spriv->type = 0;
stream_format = s->wf->wFormatTag;
@@ -2218,16 +2465,6 @@ static void mpegfile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags
stream_format, (uint32_t) len, (uint32_t) spriv->frame_size);
if(spriv->bitrate == 0)
spriv->bitrate = s->wf->nAvgBytesPerSec;
- // I need to know the audio frame size
- if(spriv->frame_size == 0)
- {
- spriv->frame_size = get_audio_frame_size(spriv, s->buffer, stream_format, s->wf->nSamplesPerSec);
- spriv->aframe_delta_pts = ((double) spriv->frame_size / (double) spriv->bitrate);
- //spriv->delta_pts = (uint64_t) (spriv->aframe_delta_pts * 92160000);
- spriv->delta_pts = (uint64_t) (92160000 * spriv->frame_size) / spriv->bitrate;
- mp_msg(MSGT_MUXER, MSGL_INFO, "AUDIO FRAME SIZE: %u, CODEC: %x, DELTA_PTS: %llu (%.3lf)\n", (uint32_t) spriv->frame_size, stream_format, spriv->delta_pts, spriv->aframe_delta_pts);
- }
-
if(s->b_buffer_size - s->b_buffer_len < len)
{
@@ -2285,20 +2522,12 @@ static void mpegfile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags
}
}
+ parse_audio(s, 0, &nf, &(s->timer));
+ s->h.dwLength += nf;
+ s->size += len;
sz = max(len, 2 * priv->packet_size);
}
- if (s->h.dwSampleSize) {
- // CBR
- s->h.dwLength += len/s->h.dwSampleSize;
- if (len%s->h.dwSampleSize) mp_msg(MSGT_MUXER, MSGL_ERR, "Warning! len isn't divisable by samplesize!\n");
- } else {
- // VBR
- s->h.dwLength++;
- }
-
- s->size += len;
- s->timer = (double)s->h.dwLength*s->h.dwScale/s->h.dwRate;
//if genmpeg1/2 and sz > last buffer size in the system header we must write the new sysheader
if(sz > s->h.dwSuggestedBufferSize) { // increase and set STD
@@ -2327,7 +2556,14 @@ static void mpegfile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags
static void mpegfile_write_index(muxer_t *muxer)
{
+ int i, nf;
muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
+
+ for(i = 0; i < muxer->avih.dwStreams; i++)
+ {
+ if(muxer->streams[i]->type == MUXER_TYPE_AUDIO)
+ parse_audio(muxer->streams[i], 1, &nf, &(muxer->streams[i]->timer));
+ }
while(flush_buffers(muxer, 0) > 0);
flush_buffers(muxer, 1);
if(priv->is_genmpeg1 || priv->is_genmpeg2)
@@ -2555,8 +2791,9 @@ int muxer_init_muxer_mpeg(muxer_t *muxer){
priv->buff = (uint8_t *) malloc(priv->packet_size);
priv->tmp = (uint8_t *) malloc(priv->packet_size);
+ priv->abuf = (uint8_t *) malloc(priv->packet_size);
priv->residual = (uint8_t *) malloc(priv->packet_size);
- if((priv->buff == NULL) || (priv->tmp == NULL) || (priv->residual == NULL))
+ if((priv->buff == NULL) || (priv->tmp == NULL) || (priv->abuf == NULL) || (priv->residual == NULL))
{
mp_msg(MSGT_MUXER, MSGL_ERR, "\nCouldn't allocate %d bytes, exit\n", priv->packet_size);
return 0;