summaryrefslogtreecommitdiffstats
path: root/libhb/encfaac.c
diff options
context:
space:
mode:
authorvan <[email protected]>2008-07-26 01:04:00 +0000
committervan <[email protected]>2008-07-26 01:04:00 +0000
commite529b1dbda55f01e21fe6fb04ee7f85c2e755725 (patch)
tree1748a00de07c035323dc9c3c9597ec9fefdeae7e /libhb/encfaac.c
parente3298b9003a7ee6070842516818bc08d8b0a65ed (diff)
- in encx264, if an video frame is larger than init_delay split it into pieces so we don't get jerky output caused by out-of-order frames.
- add an explicit EOF for all streams, not just video. - don't generate extra audio silence at the end of an encode (don't need it with explicit eof). - get rid of 80ms initial delay in AAC encode & flush final four frames buffered in encoder. - put mp4 'chap' atom on first track (usually video) rather than first audio track since we can now do video without audio (atom just needs to go on an enabled media track & video is always enabled). git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1581 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/encfaac.c')
-rw-r--r--libhb/encfaac.c94
1 files changed, 68 insertions, 26 deletions
diff --git a/libhb/encfaac.c b/libhb/encfaac.c
index 7e06a1408..645628a8e 100644
--- a/libhb/encfaac.c
+++ b/libhb/encfaac.c
@@ -16,12 +16,11 @@ struct hb_work_private_s
unsigned long input_samples;
unsigned long output_bytes;
uint8_t * buf;
-
+ uint8_t * obuf;
hb_list_t * list;
int64_t pts;
-
+ int64_t framedur;
int out_discrete_channels;
-
};
int encfaacInit( hb_work_object_t *, hb_job_t * );
@@ -57,9 +56,12 @@ int encfaacInit( hb_work_object_t * w, hb_job_t * job )
/* pass the number of channels used into the private work data */
pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);
- pv->faac = faacEncOpen( audio->config.out.samplerate, pv->out_discrete_channels, &pv->input_samples,
- &pv->output_bytes );
+ pv->faac = faacEncOpen( audio->config.out.samplerate, pv->out_discrete_channels,
+ &pv->input_samples, &pv->output_bytes );
pv->buf = malloc( pv->input_samples * sizeof( float ) );
+ pv->obuf = malloc( pv->output_bytes );
+ pv->framedur = 90000LL * pv->input_samples /
+ ( audio->config.out.samplerate * pv->out_discrete_channels );
cfg = faacEncGetCurrentConfiguration( pv->faac );
cfg->mpegVersion = MPEG4;
@@ -113,7 +115,6 @@ int encfaacInit( hb_work_object_t * w, hb_job_t * job )
free( bytes );
pv->list = hb_list_init();
- pv->pts = -1;
return 0;
}
@@ -128,6 +129,7 @@ void encfaacClose( hb_work_object_t * w )
hb_work_private_t * pv = w->private_data;
faacEncClose( pv->faac );
free( pv->buf );
+ free( pv->obuf );
hb_list_empty( &pv->list );
free( pv );
w->private_data = NULL;
@@ -141,9 +143,6 @@ void encfaacClose( hb_work_object_t * w )
static hb_buffer_t * Encode( hb_work_object_t * w )
{
hb_work_private_t * pv = w->private_data;
- hb_audio_t * audio = w->audio;
- hb_buffer_t * buf;
- uint64_t pts, pos;
if( hb_list_bytes( pv->list ) < pv->input_samples * sizeof( float ) )
{
@@ -151,31 +150,64 @@ static hb_buffer_t * Encode( hb_work_object_t * w )
return NULL;
}
+ uint64_t pts, pos;
hb_list_getbytes( pv->list, pv->buf, pv->input_samples * sizeof( float ),
&pts, &pos );
+ int size = faacEncEncode( pv->faac, (int32_t *)pv->buf, pv->input_samples,
+ pv->obuf, pv->output_bytes );
- buf = hb_buffer_init( pv->output_bytes );
- buf->start = pts + 90000 * pos / pv->out_discrete_channels / sizeof( float ) / audio->config.out.samplerate;
- buf->stop = buf->start + 90000 * pv->input_samples / audio->config.out.samplerate / pv->out_discrete_channels;
- buf->size = faacEncEncode( pv->faac, (int32_t *) pv->buf,
- pv->input_samples, buf->data, pv->output_bytes );
- buf->frametype = HB_FRAME_AUDIO;
-
- if( !buf->size )
+ // AAC needs four frames before it can start encoding so we'll get nothing
+ // on the first three calls to the encoder.
+ if ( size > 0 )
{
- /* Encoding was successful but we got no data. Try to encode
- more */
- hb_buffer_close( &buf );
- return Encode( w );
+ hb_buffer_t * buf = hb_buffer_init( size );
+ memcpy( buf->data, pv->obuf, size );
+ buf->size = size;
+ buf->start = pv->pts;
+ pv->pts += pv->framedur;
+ buf->stop = pv->pts;
+ buf->frametype = HB_FRAME_AUDIO;
+ return buf;
}
- else if( buf->size < 0 )
+ return NULL;
+}
+
+static hb_buffer_t *Flush( hb_work_object_t *w, hb_buffer_t *bufin )
+{
+ hb_work_private_t *pv = w->private_data;
+
+ // pad whatever data we have out to four input frames.
+ int nbytes = hb_list_bytes( pv->list );
+ int pad = pv->input_samples * sizeof(float) * 4 - nbytes;
+ if ( pad > 0 )
{
- hb_log( "faacEncEncode failed" );
- hb_buffer_close( &buf );
- return NULL;
+ hb_buffer_t *tmp = hb_buffer_init( pad );
+ memset( tmp->data, 0, pad );
+ hb_list_add( pv->list, tmp );
}
- return buf;
+ // There are up to three frames buffered in the encoder plus one
+ // in our list buffer so four calls to Encode should get them all.
+ hb_buffer_t *bufout = NULL, *buf = NULL;
+ while ( hb_list_bytes( pv->list ) >= pv->input_samples * sizeof(float) )
+ {
+ hb_buffer_t *b = Encode( w );
+ if ( b )
+ {
+ if ( bufout == NULL )
+ {
+ bufout = b;
+ }
+ else
+ {
+ buf->next = b;
+ }
+ buf = b;
+ }
+ }
+ // add the eof marker to the end of our buf chain
+ buf->next = bufin;
+ return bufout;
}
/***********************************************************************
@@ -189,6 +221,16 @@ int encfaacWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
hb_work_private_t * pv = w->private_data;
hb_buffer_t * buf;
+ if ( (*buf_in)->size <= 0 )
+ {
+ // EOF on input. Finish encoding what we have buffered then send
+ // it & the eof downstream.
+
+ *buf_out = Flush( w, *buf_in );
+ *buf_in = NULL;
+ return HB_WORK_DONE;
+ }
+
hb_list_add( pv->list, *buf_in );
*buf_in = NULL;