summaryrefslogtreecommitdiffstats
path: root/libhb/decavcodec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhb/decavcodec.c')
-rw-r--r--libhb/decavcodec.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c
new file mode 100644
index 000000000..4d74fc68f
--- /dev/null
+++ b/libhb/decavcodec.c
@@ -0,0 +1,134 @@
+/* $Id: decavcodec.c,v 1.6 2005/03/06 04:08:54 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "hb.h"
+
+#include "ffmpeg/avcodec.h"
+
+int decavcodecInit( hb_work_object_t *, hb_job_t * );
+int decavcodecWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
+void decavcodecClose( hb_work_object_t * );
+
+hb_work_object_t hb_decavcodec =
+{
+ WORK_DECAVCODEC,
+ "MPGA decoder (libavcodec)",
+ decavcodecInit,
+ decavcodecWork,
+ decavcodecClose
+};
+
+struct hb_work_private_s
+{
+ hb_job_t * job;
+
+ AVCodecContext * context;
+ int64_t pts_last;
+};
+
+
+/***********************************************************************
+ * hb_work_decavcodec_init
+ ***********************************************************************
+ *
+ **********************************************************************/
+int decavcodecInit( hb_work_object_t * w, hb_job_t * job )
+{
+ AVCodec * codec;
+ hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
+ w->private_data = pv;
+
+ pv->job = job;
+
+ codec = avcodec_find_decoder( CODEC_ID_MP2 );
+ pv->context = avcodec_alloc_context();
+ avcodec_open( pv->context, codec );
+ pv->pts_last = -1;
+
+ return 0;
+}
+
+/***********************************************************************
+ * Close
+ ***********************************************************************
+ *
+ **********************************************************************/
+void decavcodecClose( hb_work_object_t * w )
+{
+ hb_work_private_t * pv = w->private_data;
+ avcodec_close( pv->context );
+}
+
+/***********************************************************************
+ * Work
+ ***********************************************************************
+ *
+ **********************************************************************/
+int decavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
+ hb_buffer_t ** buf_out )
+{
+ hb_work_private_t * pv = w->private_data;
+ hb_buffer_t * in = *buf_in, * buf, * last = NULL;
+ int pos, len, out_size, i;
+ short buffer[AVCODEC_MAX_AUDIO_FRAME_SIZE];
+ uint64_t cur;
+
+ *buf_out = NULL;
+
+ if( in->start < 0 ||
+ ( pv->pts_last > 0 &&
+ in->start > pv->pts_last &&
+ in->start - pv->pts_last < 5000 ) ) /* Hacky */
+ {
+ cur = pv->pts_last;
+ }
+ else
+ {
+ cur = in->start;
+ }
+
+ pos = 0;
+ while( pos < in->size )
+ {
+ len = avcodec_decode_audio( pv->context, buffer, &out_size,
+ in->data + pos, in->size - pos );
+ if( out_size )
+ {
+ short * s16;
+ float * fl32;
+
+ buf = hb_buffer_init( 2 * out_size );
+
+ buf->start = cur;
+ buf->stop = cur + 90000 * ( out_size / 4 ) /
+ pv->context->sample_rate;
+ cur = buf->stop;
+
+ s16 = buffer;
+ fl32 = (float *) buf->data;
+ for( i = 0; i < out_size / 2; i++ )
+ {
+ fl32[i] = s16[i];
+ }
+
+ if( last )
+ {
+ last = last->next = buf;
+ }
+ else
+ {
+ *buf_out = last = buf;
+ }
+ }
+
+ pos += len;
+ }
+
+ pv->pts_last = cur;
+
+ return HB_WORK_OK;
+}
+