OSDN Git Service

Allow mac gui to select AC-3 + AAC at the same time, still needs CLI work for the...
[handbrake-jp/handbrake-jp-git.git] / libhb / work.c
index e73bf16..10f7a04 100644 (file)
@@ -22,6 +22,8 @@ static void work_func();
 static void do_job( hb_job_t *, int cpu_count );
 static void work_loop( void * );
 
+#define FIFO_CPU_MULT 8
+
 /**
  * Allocates work object and launches work thread with work_func.
  * @param jobs Handle to hb_list_t.
@@ -126,16 +128,26 @@ static void do_job( hb_job_t * job, int cpu_count )
        job->height=title->height-job->crop[0]-job->crop[1];
        job->width=title->width-job->crop[2]-job->crop[3];
     }
+    else if ( job->pixel_ratio == 2 )
+    {
+
+        /* While keeping the DVD storage aspect, resize the job width and height
+           so they fit into the user's specified dimensions. */
+        hb_set_anamorphic_size(job, &job->width, &job->height, &job->pixel_aspect_width, &job->pixel_aspect_height);
+    }
 
-       /* Keep width and height within these boundaries */
-       if (job->maxHeight && (job->height > job->maxHeight) )
+       /* Keep width and height within these boundaries,
+          but ignore for "loose" anamorphic encodes, for
+          which this stuff is covered in the pixel_ratio
+          section right above.*/
+       if (job->maxHeight && (job->height > job->maxHeight) && (job->pixel_ratio != 2))
        {
                job->height = job->maxHeight;
                hb_fix_aspect( job, HB_KEEP_HEIGHT );
                hb_log("Height out of bounds, scaling down to %i", job->maxHeight);
                hb_log("New dimensions %i * %i", job->width, job->height);
        }
-       if (job->maxWidth && (job->width > job->maxWidth) )
+       if (job->maxWidth && (job->width > job->maxWidth) && (job->pixel_ratio != 2))
        {
                job->width = job->maxWidth;
                hb_fix_aspect( job, HB_KEEP_WIDTH );   
@@ -146,7 +158,40 @@ static void do_job( hb_job_t * job, int cpu_count )
     hb_log( " + %dx%d -> %dx%d, crop %d/%d/%d/%d",
             title->width, title->height, job->width, job->height,
             job->crop[0], job->crop[1], job->crop[2], job->crop[3] );
-    hb_log( " + grayscale %s", job->grayscale ? "on" : "off" );
+
+    if ( job->grayscale )
+        hb_log( " + grayscale mode" );
+    
+    if ( job->vfr )
+    {
+        int detelecine_present = 0;        
+        if ( job->filters )
+        {
+            for( i = 0; i < hb_list_count( job->filters ); i++ )
+            {
+                hb_filter_object_t * filter = hb_list_item( job->filters, i );
+                if (filter->id == FILTER_DETELECINE)
+                    detelecine_present = 1;
+            }            
+        }
+        
+        if (!detelecine_present)
+        {
+            /* Allocate the filter. */
+            hb_filter_object_t * filter =  malloc( sizeof( hb_filter_object_t ) );
+            
+            /* Copy in the contents of the detelecine struct. */
+            memcpy( filter, &hb_filter_detelecine, sizeof( hb_filter_object_t ) );
+
+            /* Set the name to a copy of the template name so render.c has something to free. */
+            filter->name = strdup(hb_filter_detelecine.name);
+            
+            /* Add it to the list. */
+            hb_list_add( job->filters, filter );
+            
+            hb_log("work: VFR mode -- adding detelecine filter");
+        }
+    }
     
     if( job->filters )
     {
@@ -161,23 +206,31 @@ static void do_job( hb_job_t * job, int cpu_count )
         }
     }
     
+    if( job->vfr)
+    {
+        hb_log( " + video frame rate: variable (detected %.3f fps)", (float) job->vrate /
+            (float) job->vrate_base );
+    }
+    else
+    {
+        hb_log( " + video frame rate: %.3f fps", (float) job->vrate / (float) job->vrate_base);
+    }
+    
     if( job->vquality >= 0.0 && job->vquality <= 1.0 )
     {
-        hb_log( " + %.3f fps, video quality %.2f", (float) job->vrate /
-                (float) job->vrate_base, job->vquality );
+        hb_log( " + video quality %.2f", job->vquality );
     }
     else
     {
-        hb_log( " + %.3f fps, video bitrate %d kbps, pass %d",
-                (float) job->vrate / (float) job->vrate_base,
-                job->vbitrate, job->pass );
+        hb_log( " + video bitrate %d kbps, pass %d", job->vbitrate, job->pass );
     }
+
        hb_log (" + PixelRatio: %d, width:%d, height: %d",job->pixel_ratio,job->width, job->height);
     job->fifo_mpeg2  = hb_fifo_init( 2048 );
-    job->fifo_raw    = hb_fifo_init( 8 );
-    job->fifo_sync   = hb_fifo_init( 8 );
-    job->fifo_render = hb_fifo_init( 8 );
-    job->fifo_mpeg4  = hb_fifo_init( 8 );
+    job->fifo_raw    = hb_fifo_init( FIFO_CPU_MULT * cpu_count );
+    job->fifo_sync   = hb_fifo_init( FIFO_CPU_MULT * cpu_count );
+    job->fifo_render = hb_fifo_init( FIFO_CPU_MULT * cpu_count );
+    job->fifo_mpeg4  = hb_fifo_init( FIFO_CPU_MULT * cpu_count );
 
     /* Synchronization */
     hb_list_add( job->list_work, ( w = getWork( WORK_SYNC ) ) );
@@ -207,6 +260,8 @@ static void do_job( hb_job_t * job, int cpu_count )
             break;
         case HB_VCODEC_X264:
             hb_log( " + encoder x264" );
+            if( job->x264opts != NULL && *job->x264opts != '\0' )
+                hb_log( "   + x264 options: %s", job->x264opts);
             w = getWork( WORK_ENCX264 );
             break;
     }
@@ -216,7 +271,7 @@ static void do_job( hb_job_t * job, int cpu_count )
     
     hb_list_add( job->list_work, w );
 
-    if( job->select_subtitle && !job->subtitle_scan ) 
+    if( job->select_subtitle && !job->indepth_scan ) 
     {
         /*
          * Must be second pass of a two pass with subtitle scan enabled, so
@@ -237,8 +292,8 @@ static void do_job( hb_job_t * job, int cpu_count )
         {
             hb_log( " + subtitle %x, %s", subtitle->id, subtitle->lang );
             
-            subtitle->fifo_in  = hb_fifo_init( 8 );
-            subtitle->fifo_raw = hb_fifo_init( 8 );
+            subtitle->fifo_in  = hb_fifo_init( FIFO_CPU_MULT * cpu_count );
+            subtitle->fifo_raw = hb_fifo_init( FIFO_CPU_MULT * cpu_count );
             
             /*
              * Disable forced subtitles if we didn't find any in the scan
@@ -246,7 +301,7 @@ static void do_job( hb_job_t * job, int cpu_count )
              *
              * select_subtitle implies that we did a scan.
              */
-            if( !job->subtitle_scan && job->subtitle_force && 
+            if( !job->indepth_scan && job->subtitle_force && 
                 job->select_subtitle ) 
             {
                 if( subtitle->forced_hits == 0 )
@@ -255,7 +310,7 @@ static void do_job( hb_job_t * job, int cpu_count )
                 }
             }
 
-            if (!job->subtitle_scan || job->subtitle_force) {
+            if (!job->indepth_scan || job->subtitle_force) {
                 /*
                  * Don't add threads for subtitles when we are scanning, unless
                  * looking for forced subtitles.
@@ -281,6 +336,9 @@ static void do_job( hb_job_t * job, int cpu_count )
     if( job->acodec & HB_ACODEC_AC3 )
     {
         hb_log( " + audio AC3 passthrough" );
+        
+        /* Hard set correct sample rate for AC3 */
+        job->arate = 48000;
     }
     else
     {
@@ -289,8 +347,12 @@ static void do_job( hb_job_t * job, int cpu_count )
                 "faac" : ( ( job->acodec & HB_ACODEC_LAME ) ? "lame" :
                 "vorbis" ) );
     }
+    
+    if ( job->dynamic_range_compression )
+        hb_log(" + dynamic range compression: %f", job->dynamic_range_compression);
 
-    /* if we are doing AC3 passthru, then remove any non-AC3 audios from the job */
+    /* if we are doing AC3 passthru (at the codec level, not pass-through), 
+     * then remove any non-AC3 audios from the job */
     /* otherwise, Bad Things will happen */
     for( i = 0; i < hb_list_count( title->list_audio ); )
     {
@@ -324,10 +386,12 @@ static void do_job( hb_job_t * job, int cpu_count )
         /* audioCodecsSupportMono and audioCodecsSupport6Ch are the same for now,
            but this may change in the future, so they are separated for flexibility */
         int audioCodecsSupportMono = ((audio->codec == HB_ACODEC_AC3 ||
-            audio->codec == HB_ACODEC_DCA) && job->acodec == HB_ACODEC_FAAC);
+            audio->codec == HB_ACODEC_DCA) && (job->acodec == HB_ACODEC_FAAC || job->acodec == HB_ACODEC_VORBIS));
         int audioCodecsSupport6Ch =  ((audio->codec == HB_ACODEC_AC3 ||
-            audio->codec == HB_ACODEC_DCA) && job->acodec == HB_ACODEC_FAAC);
+            audio->codec == HB_ACODEC_DCA) && (job->acodec == HB_ACODEC_FAAC || job->acodec == HB_ACODEC_VORBIS));
 
+        if( job->audio_mixdowns[i] != HB_AMIXDOWN_AC3 )
+        {
         /* find out what the format of our source audio is */
         switch (audio->input_channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK) {
         
@@ -420,6 +484,7 @@ static void do_job( hb_job_t * job, int cpu_count )
                 }
 
         }
+        }
 
                /* log the output mixdown */
                for (j = 0; j < hb_audio_mixdowns_count; j++) {
@@ -435,12 +500,16 @@ static void do_job( hb_job_t * job, int cpu_count )
 
         audio->config.vorbis.language = audio->lang_simple;
 
-               /* set up the audio work structures */
+        /* set up the audio work structures */
         audio->fifo_in   = hb_fifo_init( 2048 );
-        audio->fifo_raw  = hb_fifo_init( 8 );
-        audio->fifo_sync = hb_fifo_init( 8 );
-        audio->fifo_out  = hb_fifo_init( 8 );
+        audio->fifo_raw  = hb_fifo_init( FIFO_CPU_MULT * cpu_count );
+        audio->fifo_sync = hb_fifo_init( FIFO_CPU_MULT * cpu_count );
+        audio->fifo_out  = hb_fifo_init( FIFO_CPU_MULT * cpu_count );
+
 
+        /*
+         * Audio Decoder Thread
+         */
         switch( audio->codec )
         {
             case HB_ACODEC_AC3:
@@ -468,8 +537,13 @@ static void do_job( hb_job_t * job, int cpu_count )
         
         hb_list_add( job->list_work, audio_w );
 
-        switch( job->acodec )
+        /*
+         * Audio Encoder Thread
+         */
+        if( job->audio_mixdowns[i] != HB_AMIXDOWN_AC3 )
         {
+            switch( job->acodec )
+            {
             case HB_ACODEC_FAAC:
                 w = getWork( WORK_ENCFAAC );
                 break;
@@ -479,10 +553,15 @@ static void do_job( hb_job_t * job, int cpu_count )
             case HB_ACODEC_VORBIS:
                 w = getWork( WORK_ENCVORBIS );
                 break;
+            }
         }
 
-        if( job->acodec != HB_ACODEC_AC3 )
+        if( job->acodec != HB_ACODEC_AC3 &&
+            job->audio_mixdowns[i] != HB_AMIXDOWN_AC3)
         {
+            /*
+             * Add the encoder thread if not doing AC-3 pass through
+             */
             w->fifo_in       = audio->fifo_sync;
             w->fifo_out      = audio->fifo_out;
             w->config        = &audio->config;
@@ -512,7 +591,7 @@ static void do_job( hb_job_t * job, int cpu_count )
     {
         w = hb_list_item( job->list_work, i );
         w->done = &job->done;
-               w->thread_sleep_interval = 10;
+        w->thread_sleep_interval = 10;
         w->init( w, job );
         w->thread = hb_thread_init( w->name, work_loop, w,
                                     HB_LOW_PRIORITY );
@@ -520,7 +599,7 @@ static void do_job( hb_job_t * job, int cpu_count )
 
     done = 0;
     w = hb_list_item( job->list_work, 0 );
-       w->thread_sleep_interval = 50;
+    w->thread_sleep_interval = 50;
     w->init( w, job );
     while( !*job->die )
     {
@@ -573,6 +652,7 @@ static void do_job( hb_job_t * job, int cpu_count )
     hb_fifo_close( &job->fifo_sync );
     hb_fifo_close( &job->fifo_render );
     hb_fifo_close( &job->fifo_mpeg4 );
+
     for (i=0; i < hb_list_count(title->list_subtitle); i++) {
         subtitle =  hb_list_item( title->list_subtitle, i);
         if( subtitle )
@@ -590,7 +670,7 @@ static void do_job( hb_job_t * job, int cpu_count )
         hb_fifo_close( &audio->fifo_out );
     }
 
-    if( job->subtitle_scan )
+    if( job->indepth_scan )
     {
         /*
          * Before closing the title print out our subtitle stats if we need to
@@ -614,9 +694,12 @@ static void do_job( hb_job_t * job, int cpu_count )
                 subtitle_lowest_id = subtitle->id;
             }
 
-            if ( subtitle->forced_hits > 0 )
+            if( subtitle->forced_hits > 0 )
             {
-                subtitle_forced_id = subtitle->id;
+                if( subtitle_forced_id == 0 )
+                {
+                    subtitle_forced_id = subtitle->id;
+                }
             }
         }
         
@@ -661,7 +744,7 @@ static void do_job( hb_job_t * job, int cpu_count )
 
     if( job->select_subtitle ) 
     {
-        if( job->subtitle_scan ) 
+        if( job->indepth_scan ) 
         {
             for( i=0; i < hb_list_count( title->list_subtitle ); i++ ) 
             {
@@ -684,6 +767,18 @@ static void do_job( hb_job_t * job, int cpu_count )
         }
     }
 
+    if( job->filters )
+    {
+        for( i = 0; i < hb_list_count( job->filters ); i++ )
+        {
+            hb_filter_object_t * filter = hb_list_item( job->filters, i );
+            hb_filter_close( &filter );
+        }
+        hb_list_close( &job->filters );
+    }    
+
+    hb_buffer_pool_free();
+
     hb_title_close( &job->title );
     free( job );
 }
@@ -718,10 +813,14 @@ static void work_loop( void * _w )
 
         w->work( w, &buf_in, &buf_out );
 
-        // Propogate any chapter breaks for the worker
-        if( buf_in && buf_out && buf_in->new_chap )
+        // Propagate any chapter breaks for the worker if and only if the
+        // output frame has the same time stamp as the input frame (any
+        // worker that delays frames has to propagate the chapter marks itself
+        // and workers that move chapter marks to a different time should set
+        // 'buf_in' to NULL so that this code won't generate spurious duplicates.)
+        if( buf_in && buf_out && buf_in->new_chap && buf_in->start == buf_out->start)
         {
-            hb_log("WORK: Copying Chapter Break");
+            hb_log("work %s: Copying Chapter Break @ %lld", w->name, buf_in->start);
             buf_out->new_chap = 1;
         }