OSDN Git Service

Moved functions from lang.h to lang.c for easy includion in Controller.mm
[handbrake-jp/handbrake-jp-git.git] / libhb / decavcodec.c
index f18579f..4301f43 100644 (file)
@@ -8,48 +8,51 @@
 
 #include "ffmpeg/avcodec.h"
 
-struct hb_work_object_s
+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 =
 {
-    HB_WORK_COMMON;
+    WORK_DECAVCODEC,
+    "MPGA decoder (libavcodec)",
+    decavcodecInit,
+    decavcodecWork,
+    decavcodecClose
+};
 
+struct hb_work_private_s
+{
     hb_job_t       * job;
-    hb_audio_t     * audio;
 
     AVCodecContext * context;
     int64_t          pts_last;
+    AVCodecParserContext *parser;
 };
 
 
 /***********************************************************************
- * Local prototypes
- **********************************************************************/
-static int  Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
-                  hb_buffer_t ** buf_out );
-static void Close( hb_work_object_t ** _w );
-
-/***********************************************************************
  * hb_work_decavcodec_init
  ***********************************************************************
  *
  **********************************************************************/
-hb_work_object_t * hb_work_decavcodec_init( hb_job_t * job,
-                                            hb_audio_t * audio )
+int decavcodecInit( hb_work_object_t * w, hb_job_t * job )
 {
-    hb_work_object_t * w = calloc( sizeof( hb_work_object_t ), 1 );
     AVCodec * codec;
-    w->name  = strdup( "MPGA decoder (libavcodec)" );
-    w->work  = Work;
-    w->close = Close;
-
-    w->job   = job;
-    w->audio = audio;
+    
+    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 );
-    w->context = avcodec_alloc_context();
-    avcodec_open( w->context, codec );
-    w->pts_last = -1;
+    pv->parser = av_parser_init(CODEC_ID_MP2);
+    
+    pv->context = avcodec_alloc_context();
+    avcodec_open( pv->context, codec );
+    pv->pts_last = -1;
 
-    return w;
+    return 0;
 }
 
 /***********************************************************************
@@ -57,13 +60,11 @@ hb_work_object_t * hb_work_decavcodec_init( hb_job_t * job,
  ***********************************************************************
  *
  **********************************************************************/
-static void Close( hb_work_object_t ** _w )
+void decavcodecClose( hb_work_object_t * w )
 {
-    hb_work_object_t * w = *_w;
-    avcodec_close( w->context );
-    free( w->name );
-    free( w );
-    *_w = NULL;
+    hb_work_private_t * pv = w->private_data;
+    av_parser_close(pv->parser);
+    avcodec_close( pv->context );
 }
 
 /***********************************************************************
@@ -71,22 +72,25 @@ static void Close( hb_work_object_t ** _w )
  ***********************************************************************
  *
  **********************************************************************/
-static int Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
-                 hb_buffer_t ** buf_out )
+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;
+    int   pos, len, out_size, i, uncompressed_len;
     short buffer[AVCODEC_MAX_AUDIO_FRAME_SIZE];
     uint64_t cur;
-
+    unsigned char *parser_output_buffer;
+    int parser_output_buffer_len;
+    
     *buf_out = NULL;
 
     if( in->start < 0 ||
-        ( w->pts_last > 0 &&
-          in->start > w->pts_last &&
-          in->start - w->pts_last < 5000 ) ) /* Hacky */
+        ( pv->pts_last > 0 &&
+          in->start > pv->pts_last &&
+          in->start - pv->pts_last < 5000 ) ) /* Hacky */
     {
-        cur = w->pts_last;
+        cur = pv->pts_last;
     }
     else
     {
@@ -96,8 +100,13 @@ static int Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
     pos = 0;
     while( pos < in->size )
     {
-        len = avcodec_decode_audio( w->context, buffer, &out_size,
-                                    in->data + pos, in->size - pos );
+        len = av_parser_parse(pv->parser, pv->context,&parser_output_buffer,&parser_output_buffer_len,in->data + pos,in->size - pos,cur,cur);
+        
+        out_size = 0;
+        uncompressed_len = 0;
+        if (parser_output_buffer_len)
+          uncompressed_len = avcodec_decode_audio( pv->context, buffer, &out_size,
+                                    parser_output_buffer, parser_output_buffer_len );
         if( out_size )
         {
             short * s16;
@@ -105,9 +114,22 @@ static int Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
 
             buf = hb_buffer_init( 2 * out_size );
 
+            int sample_size_in_bytes = 2;   // Default to 2 bytes
+            switch (pv->context->sample_fmt)
+            {
+              case SAMPLE_FMT_S16:
+                sample_size_in_bytes = 2;
+                break;
+              /* We should handle other formats here - but that needs additional format conversion work below */
+              /* For now we'll just report the error and try to carry on */
+              default: 
+                hb_log("decavcodecWork - Unknown Sample Format from avcodec_decode_audio (%d) !", pv->context->sample_fmt);
+                break;
+            }
+            
             buf->start = cur;
-            buf->stop  = cur + 90000 * ( out_size / 4 ) /
-                         w->context->sample_rate;
+            buf->stop  = cur + 90000 * ( out_size / (sample_size_in_bytes * pv->context->channels) ) /
+                         pv->context->sample_rate;
             cur = buf->stop;
 
             s16  = buffer;
@@ -130,7 +152,7 @@ static int Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
         pos += len;
     }
 
-    w->pts_last = cur;
+    pv->pts_last = cur;
 
     return HB_WORK_OK;
 }