예제 #1
0
파일: batch.c 프로젝트: GTRsdk/HandBrake
/***********************************************************************
 * hb_batch_title_scan
 **********************************************************************/
hb_title_t * hb_batch_title_scan( hb_batch_t * d, int t )
{

    hb_title_t   * title;
    char         * filename;
    hb_stream_t  * stream;

    if ( t < 0 )
        return NULL;

    filename = hb_list_item( d->list_file, t - 1 );
    if ( filename == NULL )
        return NULL;

    hb_log( "batch: scanning %s", filename );
    title = hb_title_init( filename, 0 );
    stream = hb_stream_open( filename, title, 1 );
    if ( stream == NULL )
    {
        hb_title_close( &title );
        return NULL;
    }

    title = hb_stream_title_scan( stream, title );
    hb_stream_close( &stream );
    if ( title != NULL )
    {
        title->index = t;
    }

    return title;
}
예제 #2
0
파일: bd.c 프로젝트: ming-hai/HandBrake
/***********************************************************************
 * hb_bd_title_scan
 **********************************************************************/
hb_title_t * hb_bd_title_scan( hb_bd_t * d, int tt, uint64_t min_duration )
{

    hb_title_t   * title;
    hb_chapter_t * chapter;
    int            ii, jj;
    BLURAY_TITLE_INFO * ti = NULL;

    hb_log( "bd: scanning title %d", tt );

    title = hb_title_init( d->path, tt );
    title->demuxer = HB_TS_DEMUXER;
    title->type = HB_BD_TYPE;
    title->reg_desc = STR4_TO_UINT32("HDMV");

    char * p_cur, * p_last = d->path;
    for( p_cur = d->path; *p_cur; p_cur++ )
    {
        if( IS_DIR_SEP(p_cur[0]) && p_cur[1] )
        {
            p_last = &p_cur[1];
        }
    }
    snprintf( title->name, sizeof( title->name ), "%s", p_last );
    char *dot_term = strrchr(title->name, '.');
    if (dot_term)
        *dot_term = '\0';

    title->vts = 0;
    title->ttn = 0;

    if (tt <= d->title_count)
    {
        ti = d->title_info[tt - 1];
    }
    if ( ti == NULL )
    {
        hb_log( "bd: invalid title" );
        goto fail;
    }
    if ( ti->clip_count == 0 )
    {
        hb_log( "bd: stream has no clips" );
        goto fail;
    }
    if ( ti->clips[0].video_stream_count == 0 )
    {
        hb_log( "bd: stream has no video" );
        goto fail;
    }

    hb_log( "bd: playlist %05d.MPLS", ti->playlist );
    title->playlist = ti->playlist;

    uint64_t pkt_count = 0;
    for ( ii = 0; ii < ti->clip_count; ii++ )
    {
        pkt_count += ti->clips[ii].pkt_count;
    }
    title->block_start = 0;
    title->block_end = pkt_count;
    title->block_count = pkt_count;

    title->angle_count = ti->angle_count;

    /* Get duration */
    title->duration = ti->duration;
    title->hours    = title->duration / 90000 / 3600;
    title->minutes  = ( ( title->duration / 90000 ) % 3600 ) / 60;
    title->seconds  = ( title->duration / 90000 ) % 60;
    hb_log( "bd: duration is %02d:%02d:%02d (%"PRIu64" ms)",
            title->hours, title->minutes, title->seconds,
            title->duration / 90 );

    /* ignore short titles because they're often stills */
    if( ti->duration < min_duration )
    {
        hb_log( "bd: ignoring title (too short)" );
        goto fail;
    }
    if (global_verbosity_level >= 2)
    {
        show_clip_list(ti);
    }

    BLURAY_STREAM_INFO * bdvideo = &ti->clips[0].video_streams[0];

    title->video_id = bdvideo->pid;
    title->video_stream_type = bdvideo->coding_type;

    hb_log( "bd: video id=0x%x, stream type=%s, format %s", title->video_id,
            bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_MPEG1 ? "MPEG1" :
            bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_MPEG2 ? "MPEG2" :
            bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_VC1 ? "VC-1" :
            bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_H264 ? "H.264" :
            "Unknown",
            bdvideo->format == BLURAY_VIDEO_FORMAT_480I ? "480i" :
            bdvideo->format == BLURAY_VIDEO_FORMAT_576I ? "576i" :
            bdvideo->format == BLURAY_VIDEO_FORMAT_480P ? "480p" :
            bdvideo->format == BLURAY_VIDEO_FORMAT_1080I ? "1080i" :
            bdvideo->format == BLURAY_VIDEO_FORMAT_720P ? "720p" :
            bdvideo->format == BLURAY_VIDEO_FORMAT_1080P ? "1080p" :
            bdvideo->format == BLURAY_VIDEO_FORMAT_576P ? "576p" :
            "Unknown"
          );

    switch( bdvideo->coding_type )
    {
        case BLURAY_STREAM_TYPE_VIDEO_MPEG1:
        case BLURAY_STREAM_TYPE_VIDEO_MPEG2:
            title->video_codec = WORK_DECAVCODECV;
            title->video_codec_param = AV_CODEC_ID_MPEG2VIDEO;
            break;

        case BLURAY_STREAM_TYPE_VIDEO_VC1:
            title->video_codec = WORK_DECAVCODECV;
            title->video_codec_param = AV_CODEC_ID_VC1;
            break;

        case BLURAY_STREAM_TYPE_VIDEO_H264:
            title->video_codec = WORK_DECAVCODECV;
            title->video_codec_param = AV_CODEC_ID_H264;
            break;

        default:
            hb_log( "scan: unknown video codec (0x%x)",
                    bdvideo->coding_type );
            goto fail;
    }

    switch ( bdvideo->aspect )
    {
        case BLURAY_ASPECT_RATIO_4_3:
            title->container_dar.num = 4;
            title->container_dar.den = 3;
            break;
        case BLURAY_ASPECT_RATIO_16_9:
            title->container_dar.num = 16;
            title->container_dar.den = 9;
            break;
        default:
            hb_log( "bd: unknown aspect" );
            goto fail;
    }
    hb_log("bd: aspect = %d:%d",
           title->container_dar.num, title->container_dar.den);

    /* Detect audio */
    // Max primary BD audios is 32
    int matches;
    int most_audio = 0;
    int audio_clip_index = 0;
    if (ti->clip_count > 2)
    {
        // All BD clips are not all required to have the same audio.
        // But clips that have seamless transition are required
        // to have the same audio as the previous clip.
        // So find the clip that has the most other clips with the 
        // matching audio.
        for ( ii = 0; ii < ti->clip_count; ii++ )
        {
            matches = 0;
            for ( jj = 0; jj < ti->clip_count; jj++ )
            {
                if ( bd_audio_equal( &ti->clips[ii], &ti->clips[jj] ) )
                {
                    matches++;
                }
            }
            if ( matches > most_audio )
            {
                most_audio = matches;
                audio_clip_index = ii;
            }
        }
    }
    else if (ti->clip_count == 2)
    {
        // If there are only 2 clips, pick audios from the longer clip
        if (ti->clips[0].pkt_count < ti->clips[1].pkt_count)
            audio_clip_index = 1;
    }

    // Add all the audios found in the above clip.
    for (ii = 0; ii < ti->clips[audio_clip_index].audio_stream_count; ii++)
    {
        BLURAY_STREAM_INFO * bdaudio;

        bdaudio = &ti->clips[audio_clip_index].audio_streams[ii];

        switch (bdaudio->coding_type)
        {
            case BLURAY_STREAM_TYPE_AUDIO_TRUHD:
                // Add 2 audio tracks.  One for TrueHD and one for AC-3
                add_audio(ii, title->list_audio, bdaudio, HB_SUBSTREAM_BD_AC3,
                          HB_ACODEC_AC3, AV_CODEC_ID_AC3);
                add_audio(ii, title->list_audio, bdaudio, HB_SUBSTREAM_BD_TRUEHD,
                          HB_ACODEC_FFTRUEHD, AV_CODEC_ID_TRUEHD);
                break;

            case BLURAY_STREAM_TYPE_AUDIO_DTS:
                add_audio(ii, title->list_audio, bdaudio, 0,
                          HB_ACODEC_DCA, AV_CODEC_ID_DTS);
                break;

            case BLURAY_STREAM_TYPE_AUDIO_MPEG2:
            case BLURAY_STREAM_TYPE_AUDIO_MPEG1:
                add_audio(ii, title->list_audio, bdaudio, 0,
                          HB_ACODEC_FFMPEG, AV_CODEC_ID_MP2);
                break;

            case BLURAY_STREAM_TYPE_AUDIO_AC3PLUS:
                add_audio(ii, title->list_audio, bdaudio, 0,
                          HB_ACODEC_FFEAC3, AV_CODEC_ID_EAC3);
                break;

            case BLURAY_STREAM_TYPE_AUDIO_LPCM:
                add_audio(ii, title->list_audio, bdaudio, 0,
                          HB_ACODEC_FFMPEG, AV_CODEC_ID_PCM_BLURAY);
                break;

            case BLURAY_STREAM_TYPE_AUDIO_AC3:
                add_audio(ii, title->list_audio, bdaudio, 0,
                          HB_ACODEC_AC3, AV_CODEC_ID_AC3);
                break;

            case BLURAY_STREAM_TYPE_AUDIO_DTSHD_MASTER:
            case BLURAY_STREAM_TYPE_AUDIO_DTSHD:
                // Add 2 audio tracks.  One for DTS-HD and one for DTS
                add_audio(ii, title->list_audio, bdaudio, HB_SUBSTREAM_BD_DTS,
                          HB_ACODEC_DCA, AV_CODEC_ID_DTS);
                // DTS-HD is special.  The substreams must be concatinated
                // DTS-core followed by DTS-hd-extensions.  Setting
                // a substream id of 0 says use all substreams.
                add_audio(ii, title->list_audio, bdaudio, 0,
                          HB_ACODEC_DCA_HD, AV_CODEC_ID_DTS);
                break;

            default:
                hb_log("scan: unknown audio pid 0x%x codec 0x%x", bdaudio->pid,
                       bdaudio->coding_type);
                break;
        }
    }

    // Add all the subtitles found in the above clip.
    for ( ii = 0; ii < ti->clips[audio_clip_index].pg_stream_count; ii++ )
    {
        BLURAY_STREAM_INFO * bdpgs;

        bdpgs = &ti->clips[audio_clip_index].pg_streams[ii];

        switch( bdpgs->coding_type )
        {
            case BLURAY_STREAM_TYPE_SUB_PG:
                add_subtitle(ii, title->list_subtitle, bdpgs, WORK_DECPGSSUB);
                break;
            default:
                hb_log( "scan: unknown subtitle pid 0x%x codec 0x%x",
                        bdpgs->pid, bdpgs->coding_type );
                break;
        }
    }

    /* Chapters */
    for ( ii = 0, jj = 0; ii < ti->chapter_count; ii++ )
    {
        char chapter_title[80];

        // Sanity check start time of this chapter.
        // If it is beyond the end of the title, drop it.
        if (ti->chapters[ii].start > ti->duration)
        {
            hb_log("bd: chapter %d invalid start %"PRIu64", dropping", ii+1,
                   ti->chapters[ii].start);
            continue;
        }

        chapter = calloc( sizeof( hb_chapter_t ), 1 );

        chapter->index = ++jj;
        sprintf( chapter_title, "Chapter %d", chapter->index );
        hb_chapter_set_title( chapter, chapter_title );

        chapter->duration = ti->chapters[ii].duration;
        chapter->block_start = ti->chapters[ii].offset;

        // Sanity check chapter duration and start times
        // Have seen some invalid durations in the wild
        if (ii < ti->chapter_count - 1)
        {
            // Validate start time
            if (ti->chapters[ii+1].start < ti->chapters[ii].start)
            {
                hb_log("bd: chapter %d invalid start %"PRIu64"", ii+1,
                       ti->chapters[ii+1].start);
                ti->chapters[ii+1].start = ti->chapters[ii].start +
                                           chapter->duration;
            }
            if (ti->chapters[ii+1].start - ti->chapters[ii].start !=
                chapter->duration)
            {
                hb_log("bd: chapter %d invalid duration %"PRIu64"", ii+1,
                       chapter->duration);
                chapter->duration = ti->chapters[ii+1].start -
                                    ti->chapters[ii].start;
            }
        }
        else
        {
            if (ti->duration - ti->chapters[ii].start != chapter->duration)
            {
                hb_log("bd: chapter %d invalid duration %"PRIu64"", ii+1,
                       chapter->duration);
                chapter->duration = ti->duration - ti->chapters[ii].start;
            }
        }

        int seconds      = ( chapter->duration + 45000 ) / 90000;
        chapter->hours   = ( seconds / 3600 );
        chapter->minutes = ( seconds % 3600 ) / 60;
        chapter->seconds = ( seconds % 60 );

        hb_log( "bd: chap %d packet=%"PRIu64", %"PRIu64" ms",
                chapter->index,
                chapter->block_start,
                chapter->duration / 90 );

        hb_list_add( title->list_chapter, chapter );
    }
    hb_log( "bd: title %d has %d chapters", tt, ti->chapter_count );

    /* This title is ok so far */
    goto cleanup;

fail:
    hb_title_close( &title );

cleanup:

    return title;
}
예제 #3
0
파일: scan.c 프로젝트: ming-hai/HandBrake
static void ScanFunc( void * _data )
{
    hb_scan_t  * data = (hb_scan_t *) _data;
    hb_title_t * title;
    int          i;
    int          feature = 0;

    data->bd = NULL;
    data->dvd = NULL;
    data->stream = NULL;

    /* Try to open the path as a DVD. If it fails, try as a file */
    if( ( data->bd = hb_bd_init( data->h, data->path ) ) )
    {
        hb_log( "scan: BD has %d title(s)",
                hb_bd_title_count( data->bd ) );
        if( data->title_index )
        {
            /* Scan this title only */
            hb_list_add( data->title_set->list_title,
                         hb_bd_title_scan( data->bd,
                         data->title_index, 0 ) );
        }
        else
        {
            /* Scan all titles */
            for( i = 0; i < hb_bd_title_count( data->bd ); i++ )
            {
                UpdateState1(data, i + 1);
                hb_list_add( data->title_set->list_title,
                             hb_bd_title_scan( data->bd,
                             i + 1, data->min_title_duration ) );
            }
            feature = hb_bd_main_feature( data->bd,
                                          data->title_set->list_title );
        }
    }
    else if( ( data->dvd = hb_dvd_init( data->h, data->path ) ) )
    {
        hb_log( "scan: DVD has %d title(s)",
                hb_dvd_title_count( data->dvd ) );
        if( data->title_index )
        {
            /* Scan this title only */
            hb_list_add( data->title_set->list_title,
                         hb_dvd_title_scan( data->dvd,
                            data->title_index, 0 ) );
        }
        else
        {
            /* Scan all titles */
            for( i = 0; i < hb_dvd_title_count( data->dvd ); i++ )
            {
                UpdateState1(data, i + 1);
                hb_list_add( data->title_set->list_title,
                             hb_dvd_title_scan( data->dvd,
                            i + 1, data->min_title_duration ) );
            }
            feature = hb_dvd_main_feature( data->dvd,
                                           data->title_set->list_title );
        }
    }
    else if ( ( data->batch = hb_batch_init( data->h, data->path ) ) )
    {
        if( data->title_index )
        {
            /* Scan this title only */
            title = hb_batch_title_scan(data->batch, data->title_index, 0);
            if ( title )
            {
                hb_list_add( data->title_set->list_title, title );
            }
        }
        else
        {
            /* Scan all titles */
            for( i = 0; i < hb_batch_title_count( data->batch ); i++ )
            {
                hb_title_t * title;

                UpdateState1(data, i + 1);
                title = hb_batch_title_scan(data->batch, i + 1,
                                            data->min_title_duration);
                if ( title != NULL )
                {
                    hb_list_add( data->title_set->list_title, title );
                }
            }
        }
    }
    else
    {
        // Title index 0 is not a valid title number and means scan all titles.
        // So set title index to 1 in this scenario.
        //
        // Otherwise, set title index in new title to the index that was
        // requested.  This preserves the original index created in batch
        // mode.
        if (data->title_index == 0)
            data->title_index = 1;
        hb_title_t * title = hb_title_init( data->path, data->title_index );
        data->stream = hb_stream_open(data->h, data->path, title, 1);
        if (data->stream != NULL)
        {
            title = hb_stream_title_scan( data->stream, title );
            if ( title )
                hb_list_add( data->title_set->list_title, title );
        }
        else
        {
            hb_title_close( &title );
            hb_log( "scan: unrecognized file type" );
            goto finish;
        }
    }

    for( i = 0; i < hb_list_count( data->title_set->list_title ); )
    {
        int j, npreviews;
        hb_audio_t * audio;

        if ( *data->die )
        {
            goto finish;
        }
        title = hb_list_item( data->title_set->list_title, i );

        UpdateState2(data, i + 1);

        /* Decode previews */
        /* this will also detect more AC3 / DTS information */
        npreviews = DecodePreviews( data, title, 1 );
        if (npreviews < 2)
        {
            // Try harder to get some valid frames
            // Allow libav to return "corrupt" frames
            hb_log("scan: Too few previews (%d), trying harder", npreviews);
            title->flags |= HBTF_NO_IDR;
            npreviews = DecodePreviews( data, title, 0 );
        }
        if (npreviews == 0)
        {
            /* TODO: free things */
            hb_list_rem( data->title_set->list_title, title );
            for( j = 0; j < hb_list_count( title->list_audio ); j++)
            {
                audio = hb_list_item( title->list_audio, j );
                if ( audio->priv.scan_cache )
                {
                    hb_fifo_flush( audio->priv.scan_cache );
                    hb_fifo_close( &audio->priv.scan_cache );
                }
            }
            hb_title_close( &title );
            continue;
        }
        title->preview_count = npreviews;

        /* Make sure we found audio rates and bitrates */
        for( j = 0; j < hb_list_count( title->list_audio ); )
        {
            audio = hb_list_item( title->list_audio, j );
            if ( audio->priv.scan_cache )
            {
                hb_fifo_flush( audio->priv.scan_cache );
                hb_fifo_close( &audio->priv.scan_cache );
            }
            if( !audio->config.in.bitrate )
            {
                hb_log( "scan: removing audio 0x%x because no bitrate found",
                        audio->id );
                hb_list_rem( title->list_audio, audio );
                free( audio );
                continue;
            }
            j++;
        }

        // VOBSUB and PGS width and height needs to be set to the
        // title width and height for any stream type that does
        // not provide this information (DVDs, BDs, VOBs, and M2TSs).
        // Title width and height don't get set until we decode
        // previews, so we can't set subtitle width/height till
        // we get here.
        for (j = 0; j < hb_list_count(title->list_subtitle); j++)
        {
            hb_subtitle_t *subtitle = hb_list_item(title->list_subtitle, j);
            if ((subtitle->source == VOBSUB || subtitle->source == PGSSUB) &&
                (subtitle->width <= 0 || subtitle->height <= 0))
            {
                subtitle->width  = title->geometry.width;
                subtitle->height = title->geometry.height;
            }
        }
        i++;
    }

    data->title_set->feature = feature;

    /* Mark title scan complete and init jobs */
    for( i = 0; i < hb_list_count( data->title_set->list_title ); i++ )
    {
        title      = hb_list_item( data->title_set->list_title, i );
        title->flags |= HBTF_SCAN_COMPLETE;
    }
    if (hb_list_count(data->title_set->list_title) > 0)
    {
        strncpy(data->title_set->path, data->path, 1024);
        data->title_set->path[1023] = 0;
    }
    else
    {
        data->title_set->path[0] = 0;
    }

finish:

    if( data->bd )
    {
        hb_bd_close( &data->bd );
    }
    if( data->dvd )
    {
        hb_dvd_close( &data->dvd );
    }
    if (data->stream)
    {
        hb_stream_close(&data->stream);
    }
    if( data->batch )
    {
        hb_batch_close( &data->batch );
    }
    free( data->path );
    free( data );
    _data = NULL;
    hb_buffer_pool_free();
}
예제 #4
0
파일: scan.c 프로젝트: GTRsdk/HandBrake
static void ScanFunc( void * _data )
{
    hb_scan_t  * data = (hb_scan_t *) _data;
    hb_title_t * title;
    int          i;
    int          feature = 0;

    data->bd = NULL;
    data->dvd = NULL;
    data->stream = NULL;

    /* Try to open the path as a DVD. If it fails, try as a file */
    if( ( data->bd = hb_bd_init( data->path ) ) )
    {
        hb_log( "scan: BD has %d title(s)",
                hb_bd_title_count( data->bd ) );
        if( data->title_index )
        {
            /* Scan this title only */
            hb_list_add( data->list_title, hb_bd_title_scan( data->bd,
                         data->title_index, 0 ) );
        }
        else
        {
            /* Scan all titles */
            for( i = 0; i < hb_bd_title_count( data->bd ); i++ )
            {
                hb_list_add( data->list_title, hb_bd_title_scan( data->bd, 
                             i + 1, data->min_title_duration ) );
            }
            feature = hb_bd_main_feature( data->bd, data->list_title );
        }
    }
    else if( ( data->dvd = hb_dvd_init( data->path ) ) )
    {
        hb_log( "scan: DVD has %d title(s)",
                hb_dvd_title_count( data->dvd ) );
        if( data->title_index )
        {
            /* Scan this title only */
            hb_list_add( data->list_title, hb_dvd_title_scan( data->dvd,
                            data->title_index, 0 ) );
        }
        else
        {
            /* Scan all titles */
            for( i = 0; i < hb_dvd_title_count( data->dvd ); i++ )
            {
                hb_list_add( data->list_title, hb_dvd_title_scan( data->dvd, 
                            i + 1, data->min_title_duration ) );
            }
            feature = hb_dvd_main_feature( data->dvd, data->list_title );
        }
    }
    else if ( ( data->batch = hb_batch_init( data->path ) ) )
    {
        if( data->title_index )
        {
            /* Scan this title only */
            title = hb_batch_title_scan( data->batch, data->title_index );
            if ( title )
            {
                hb_list_add( data->list_title, title );
            }
        }
        else
        {
            /* Scan all titles */
            for( i = 0; i < hb_batch_title_count( data->batch ); i++ )
            {
                hb_title_t * title;

                title = hb_batch_title_scan( data->batch, i + 1 );
                if ( title != NULL )
                {
                    hb_list_add( data->list_title, title );
                }
            }
        }
    }
    else
    {
        hb_title_t * title = hb_title_init( data->path, 0 );
        if ( (data->stream = hb_stream_open( data->path, title, 1 ) ) != NULL )
        {
            title = hb_stream_title_scan( data->stream, title );
            if ( title )
                hb_list_add( data->list_title, title );
        }
        else
        {
            hb_title_close( &title );
            hb_log( "scan: unrecognized file type" );
            return;
        }
    }

    for( i = 0; i < hb_list_count( data->list_title ); )
    {
        int j;
        hb_state_t state;
        hb_audio_t * audio;

        if ( *data->die )
        {
            goto finish;
        }
        title = hb_list_item( data->list_title, i );

#define p state.param.scanning
        /* Update the UI */
        state.state   = HB_STATE_SCANNING;
        p.title_cur   = title->index;
        p.title_count = data->dvd ? hb_dvd_title_count( data->dvd ) : 
                        data->bd ? hb_bd_title_count( data->bd ) :
                        data->batch ? hb_batch_title_count( data->batch ) :
                                   hb_list_count(data->list_title);
        hb_set_state( data->h, &state );
#undef p

        /* Decode previews */
        /* this will also detect more AC3 / DTS information */
        if( !DecodePreviews( data, title ) )
        {
            /* TODO: free things */
            hb_list_rem( data->list_title, title );
            for( j = 0; j < hb_list_count( title->list_audio ); j++)
            {
                audio = hb_list_item( title->list_audio, j );
                if ( audio->priv.scan_cache )
                {
                    hb_fifo_flush( audio->priv.scan_cache );
                    hb_fifo_close( &audio->priv.scan_cache );
                }
            }
            hb_title_close( &title );
            continue;
        }

        /* Make sure we found audio rates and bitrates */
        for( j = 0; j < hb_list_count( title->list_audio ); )
        {
            audio = hb_list_item( title->list_audio, j );
            if ( audio->priv.scan_cache )
            {
                hb_fifo_flush( audio->priv.scan_cache );
                hb_fifo_close( &audio->priv.scan_cache );
            }
            if( !audio->config.in.bitrate )
            {
                hb_log( "scan: removing audio 0x%x because no bitrate found",
                        audio->id );
                hb_list_rem( title->list_audio, audio );
                free( audio );
                continue;
            }
            j++;
        }

        if ( data->dvd || data->bd )
        {
            // The subtitle width and height needs to be set to the 
            // title widht and height for DVDs.  title width and
            // height don't get set until we decode previews, so
            // we can't set subtitle width/height till we get here.
            for( j = 0; j < hb_list_count( title->list_subtitle ); j++ )
            {
                hb_subtitle_t *subtitle = hb_list_item( title->list_subtitle, j );
                if ( subtitle->source == VOBSUB || subtitle->source == PGSSUB )
                {
                    subtitle->width = title->width;
                    subtitle->height = title->height;
                }
            }
        }
        i++;
    }

    /* Init jobs templates */
    for( i = 0; i < hb_list_count( data->list_title ); i++ )
    {
        hb_job_t * job;

        title      = hb_list_item( data->list_title, i );
        job        = calloc( sizeof( hb_job_t ), 1 );
        title->job = job;

        job->title = title;
        job->feature = feature;

        /* Set defaults settings */
        job->chapter_start = 1;
        job->chapter_end   = hb_list_count( title->list_chapter );

        /* Autocrop by default. Gnark gnark */
        memcpy( job->crop, title->crop, 4 * sizeof( int ) );

        /* Preserve a source's pixel aspect, if it's available. */
        if( title->pixel_aspect_width && title->pixel_aspect_height )
        {
            job->anamorphic.par_width  = title->pixel_aspect_width;
            job->anamorphic.par_height = title->pixel_aspect_height;
        }

        if( title->aspect != 0 && title->aspect != 1. &&
            !job->anamorphic.par_width && !job->anamorphic.par_height)
        {
            hb_reduce( &job->anamorphic.par_width, &job->anamorphic.par_height,
                       (int)(title->aspect * title->height + 0.5), title->width );
        }

        job->width = title->width - job->crop[2] - job->crop[3];
        hb_fix_aspect( job, HB_KEEP_WIDTH );
        if( job->height > title->height - job->crop[0] - job->crop[1] )
        {
            job->height = title->height - job->crop[0] - job->crop[1];
            hb_fix_aspect( job, HB_KEEP_HEIGHT );
        }

        hb_log( "scan: title (%d) job->width:%d, job->height:%d",
                i, job->width, job->height );

        job->keep_ratio = 1;

        job->vcodec     = HB_VCODEC_FFMPEG_MPEG4;
        job->vquality   = -1.0;
        job->vbitrate   = 1000;
        job->pass       = 0;
        job->vrate      = title->rate;
        job->vrate_base = title->rate_base;

        job->list_audio = hb_list_init();
        job->list_subtitle = hb_list_init();
        job->list_filter = hb_list_init();

        job->mux = HB_MUX_MP4;
    }

finish:

    if( data->bd )
    {
        hb_bd_close( &data->bd );
    }
    if( data->dvd )
    {
        hb_dvd_close( &data->dvd );
    }
    if (data->stream)
    {
        hb_stream_close(&data->stream);
    }
    if( data->batch )
    {
        hb_batch_close( &data->batch );
    }
    free( data->path );
    free( data );
    _data = NULL;
}
예제 #5
0
파일: bd.c 프로젝트: eneko/HandBrake
/***********************************************************************
 * hb_bd_title_scan
 **********************************************************************/
hb_title_t * hb_bd_title_scan( hb_bd_t * d, int tt, uint64_t min_duration )
{

    hb_title_t   * title;
    hb_chapter_t * chapter;
    int            ii, jj;
    BLURAY_TITLE_INFO * ti = NULL;

    hb_log( "bd: scanning title %d", tt );

    title = hb_title_init( d->path, tt );
    title->demuxer = HB_MPEG_DEMUXER;
    title->type = HB_BD_TYPE;
    title->reg_desc = STR4_TO_UINT32("HDMV");

    char * p_cur, * p_last = d->path;
    for( p_cur = d->path; *p_cur; p_cur++ )
    {
        if( p_cur[0] == '/' && p_cur[1] )
        {
            p_last = &p_cur[1];
        }
    }
    snprintf( title->name, sizeof( title->name ), "%s", p_last );
    strncpy( title->path, d->path, 1024 );
    title->path[1023] = 0;

    title->vts = 0;
    title->ttn = 0;

    ti = d->title_info[tt - 1];
    if ( ti == NULL )
    {
        hb_log( "bd: invalid title" );
        goto fail;
    }
    if ( ti->clip_count == 0 )
    {
        hb_log( "bd: stream has no clips" );
        goto fail;
    }
    if ( ti->clips[0].video_stream_count == 0 )
    {
        hb_log( "bd: stream has no video" );
        goto fail;
    }

    hb_log( "bd: playlist %05d.MPLS", ti->playlist );
    title->playlist = ti->playlist;

    uint64_t pkt_count = 0;
    for ( ii = 0; ii < ti->clip_count; ii++ )
    {
        pkt_count += ti->clips[ii].pkt_count;
    }
    title->block_start = 0;
    title->block_end = pkt_count;
    title->block_count = pkt_count;

    title->angle_count = ti->angle_count;

    /* Get duration */
    title->duration = ti->duration;
    title->hours    = title->duration / 90000 / 3600;
    title->minutes  = ( ( title->duration / 90000 ) % 3600 ) / 60;
    title->seconds  = ( title->duration / 90000 ) % 60;
    hb_log( "bd: duration is %02d:%02d:%02d (%"PRId64" ms)",
            title->hours, title->minutes, title->seconds,
            title->duration / 90 );

    /* ignore short titles because they're often stills */
    if( ti->duration < min_duration )
    {
        hb_log( "bd: ignoring title (too short)" );
        goto fail;
    }

    BLURAY_STREAM_INFO * bdvideo = &ti->clips[0].video_streams[0];

    title->video_id = bdvideo->pid;
    title->video_stream_type = bdvideo->coding_type;

    hb_log( "bd: video id=0x%x, stream type=%s, format %s", title->video_id,
            bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_MPEG1 ? "MPEG1" :
            bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_MPEG2 ? "MPEG2" :
            bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_VC1 ? "VC-1" :
            bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_H264 ? "H.264" :
            "Unknown",
            bdvideo->format == BLURAY_VIDEO_FORMAT_480I ? "480i" :
            bdvideo->format == BLURAY_VIDEO_FORMAT_576I ? "576i" :
            bdvideo->format == BLURAY_VIDEO_FORMAT_480P ? "480p" :
            bdvideo->format == BLURAY_VIDEO_FORMAT_1080I ? "1080i" :
            bdvideo->format == BLURAY_VIDEO_FORMAT_720P ? "720p" :
            bdvideo->format == BLURAY_VIDEO_FORMAT_1080P ? "1080p" :
            bdvideo->format == BLURAY_VIDEO_FORMAT_576P ? "576p" :
            "Unknown"
          );

    if ( bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_VC1 &&
       ( bdvideo->format == BLURAY_VIDEO_FORMAT_480I ||
         bdvideo->format == BLURAY_VIDEO_FORMAT_576I ||
         bdvideo->format == BLURAY_VIDEO_FORMAT_1080I ) )
    {
        hb_log( "bd: Interlaced VC-1 not supported" );
        goto fail;
    }

    switch( bdvideo->coding_type )
    {
        case BLURAY_STREAM_TYPE_VIDEO_MPEG1:
        case BLURAY_STREAM_TYPE_VIDEO_MPEG2:
            title->video_codec = WORK_DECMPEG2;
            title->video_codec_param = 0;
            break;

        case BLURAY_STREAM_TYPE_VIDEO_VC1:
            title->video_codec = WORK_DECAVCODECV;
            title->video_codec_param = CODEC_ID_VC1;
            break;

        case BLURAY_STREAM_TYPE_VIDEO_H264:
            title->video_codec = WORK_DECAVCODECV;
            title->video_codec_param = CODEC_ID_H264;
            title->flags |= HBTF_NO_IDR;
            break;

        default:
            hb_log( "scan: unknown video codec (0x%x)",
                    bdvideo->coding_type );
            goto fail;
    }

    switch ( bdvideo->aspect )
    {
        case BLURAY_ASPECT_RATIO_4_3:
            title->container_aspect = 4. / 3.;
            break;
        case BLURAY_ASPECT_RATIO_16_9:
            title->container_aspect = 16. / 9.;
            break;
        default:
            hb_log( "bd: unknown aspect" );
            goto fail;
    }
    hb_log( "bd: aspect = %g", title->container_aspect );

    /* Detect audio */
    // All BD clips are not all required to have the same audio.
    // But clips that have seamless transition are required
    // to have the same audio as the previous clip.
    // So find the clip that has the most other clips with the 
    // matching audio.
    // Max primary BD audios is 32
    int matches;
    int most_audio = 0;
    int audio_clip_index = 0;
    for ( ii = 0; ii < ti->clip_count; ii++ )
    {
        matches = 0;
        for ( jj = 0; jj < ti->clip_count; jj++ )
        {
            if ( bd_audio_equal( &ti->clips[ii], &ti->clips[jj] ) )
            {
                matches++;
            }
        }
        if ( matches > most_audio )
        {
            most_audio = matches;
            audio_clip_index = ii;
        }
    }

    // Add all the audios found in the above clip.
    for ( ii = 0; ii < ti->clips[audio_clip_index].audio_stream_count; ii++ )
    {
        BLURAY_STREAM_INFO * bdaudio;

        bdaudio = &ti->clips[audio_clip_index].audio_streams[ii];

        switch( bdaudio->coding_type )
        {
            case BLURAY_STREAM_TYPE_AUDIO_TRUHD:
                // Add 2 audio tracks.  One for TrueHD and one for AC-3
                add_audio(ii, title->list_audio, bdaudio, 
                          HB_SUBSTREAM_BD_AC3, HB_ACODEC_AC3, 0);
                add_audio(ii, title->list_audio, bdaudio, 
                    HB_SUBSTREAM_BD_TRUEHD, HB_ACODEC_FFMPEG, CODEC_ID_TRUEHD);
                break;

            case BLURAY_STREAM_TYPE_AUDIO_DTS:
                add_audio(ii, title->list_audio, bdaudio, 0, HB_ACODEC_DCA, 0);
                break;

            case BLURAY_STREAM_TYPE_AUDIO_MPEG2:
            case BLURAY_STREAM_TYPE_AUDIO_MPEG1:
                add_audio(ii, title->list_audio, bdaudio, 0, 
                          HB_ACODEC_FFMPEG, CODEC_ID_MP2);
                break;

            case BLURAY_STREAM_TYPE_AUDIO_AC3PLUS:
                add_audio(ii, title->list_audio, bdaudio, 0, 
                          HB_ACODEC_FFMPEG, CODEC_ID_EAC3);
                break;

            case BLURAY_STREAM_TYPE_AUDIO_LPCM:
                add_audio(ii, title->list_audio, bdaudio, 0, 
                          HB_ACODEC_FFMPEG, CODEC_ID_PCM_BLURAY);
                break;

            case BLURAY_STREAM_TYPE_AUDIO_AC3:
                add_audio(ii, title->list_audio, bdaudio, 0, HB_ACODEC_AC3, 0);
                break;

            case BLURAY_STREAM_TYPE_AUDIO_DTSHD_MASTER:
            case BLURAY_STREAM_TYPE_AUDIO_DTSHD:
                // Add 2 audio tracks.  One for DTS-HD and one for DTS
                add_audio(ii, title->list_audio, bdaudio, HB_SUBSTREAM_BD_DTS, 
                          HB_ACODEC_DCA, 0);
                // DTS-HD is special.  The substreams must be concatinated
                // DTS-core followed by DTS-hd-extensions.  Setting
                // a substream id of 0 says use all substreams.
                add_audio(ii, title->list_audio, bdaudio, 0,
                          HB_ACODEC_DCA_HD, CODEC_ID_DTS);
                break;

            default:
                hb_log( "scan: unknown audio pid 0x%x codec 0x%x",
                        bdaudio->pid, bdaudio->coding_type );
                break;
        }
    }

    // Add all the subtitles found in the above clip.
    for ( ii = 0; ii < ti->clips[audio_clip_index].pg_stream_count; ii++ )
    {
        BLURAY_STREAM_INFO * bdpgs;

        bdpgs = &ti->clips[audio_clip_index].pg_streams[ii];

        switch( bdpgs->coding_type )
        {
            case BLURAY_STREAM_TYPE_SUB_PG:
                add_subtitle(ii, title->list_subtitle, bdpgs, WORK_DECPGSSUB);
                break;
            default:
                hb_log( "scan: unknown subtitle pid 0x%x codec 0x%x",
                        bdpgs->pid, bdpgs->coding_type );
                break;
        }
    }

    /* Chapters */
    for ( ii = 0; ii < ti->chapter_count; ii++ )
    {
        chapter = calloc( sizeof( hb_chapter_t ), 1 );

        chapter->index = ii + 1;
        sprintf( chapter->title, "Chapter %d", chapter->index );

        chapter->duration = ti->chapters[ii].duration;
        chapter->block_start = ti->chapters[ii].offset;

        int seconds      = ( chapter->duration + 45000 ) / 90000;
        chapter->hours   = ( seconds / 3600 );
        chapter->minutes = ( seconds % 3600 ) / 60;
        chapter->seconds = ( seconds % 60 );

        hb_log( "bd: chap %d packet=%"PRIu64", %"PRId64" ms",
                chapter->index,
                chapter->block_start,
                chapter->duration / 90 );

        hb_list_add( title->list_chapter, chapter );
    }
    hb_log( "bd: title %d has %d chapters", tt, ti->chapter_count );

    /* This title is ok so far */
    goto cleanup;

fail:
    hb_title_close( &title );

cleanup:

    return title;
}
예제 #6
0
파일: scan.c 프로젝트: Vanganesha/HandBrake
static void ScanFunc( void * _data )
{
    hb_scan_t  * data = (hb_scan_t *) _data;
    hb_title_t * title;
    int          i;
    int          feature = 0;

    data->bd = NULL;
    data->dvd = NULL;
    data->stream = NULL;

    /* Try to open the path as a DVD. If it fails, try as a file */
    if( ( data->bd = hb_bd_init( data->path ) ) )
    {
        hb_log( "scan: BD has %d title(s)",
                hb_bd_title_count( data->bd ) );
        if( data->title_index )
        {
            /* Scan this title only */
            hb_list_add( data->title_set->list_title,
                         hb_bd_title_scan( data->bd,
                         data->title_index, 0 ) );
        }
        else
        {
            /* Scan all titles */
            for( i = 0; i < hb_bd_title_count( data->bd ); i++ )
            {
                UpdateState1(data, i + 1);
                hb_list_add( data->title_set->list_title,
                             hb_bd_title_scan( data->bd, 
                             i + 1, data->min_title_duration ) );
            }
            feature = hb_bd_main_feature( data->bd,
                                          data->title_set->list_title );
        }
    }
    else if( ( data->dvd = hb_dvd_init( data->path ) ) )
    {
        hb_log( "scan: DVD has %d title(s)",
                hb_dvd_title_count( data->dvd ) );
        if( data->title_index )
        {
            /* Scan this title only */
            hb_list_add( data->title_set->list_title,
                         hb_dvd_title_scan( data->dvd,
                            data->title_index, 0 ) );
        }
        else
        {
            /* Scan all titles */
            for( i = 0; i < hb_dvd_title_count( data->dvd ); i++ )
            {
                UpdateState1(data, i + 1);
                hb_list_add( data->title_set->list_title,
                             hb_dvd_title_scan( data->dvd, 
                            i + 1, data->min_title_duration ) );
            }
            feature = hb_dvd_main_feature( data->dvd,
                                           data->title_set->list_title );
        }
    }
    else if ( ( data->batch = hb_batch_init( data->path ) ) )
    {
        if( data->title_index )
        {
            /* Scan this title only */
            title = hb_batch_title_scan( data->batch, data->title_index );
            if ( title )
            {
                hb_list_add( data->title_set->list_title, title );
            }
        }
        else
        {
            /* Scan all titles */
            for( i = 0; i < hb_batch_title_count( data->batch ); i++ )
            {
                hb_title_t * title;

                UpdateState1(data, i + 1);
                title = hb_batch_title_scan( data->batch, i + 1 );
                if ( title != NULL )
                {
                    hb_list_add( data->title_set->list_title, title );
                }
            }
        }
    }
    else
    {
        data->title_index = 1;
        hb_title_t * title = hb_title_init( data->path, data->title_index );
        if ( (data->stream = hb_stream_open( data->path, title, 1 ) ) != NULL )
        {
            title = hb_stream_title_scan( data->stream, title );
            if ( title )
                hb_list_add( data->title_set->list_title, title );
        }
        else
        {
            hb_title_close( &title );
            hb_log( "scan: unrecognized file type" );
            return;
        }
    }

    for( i = 0; i < hb_list_count( data->title_set->list_title ); )
    {
        int j;
        hb_audio_t * audio;

        if ( *data->die )
        {
            goto finish;
        }
        title = hb_list_item( data->title_set->list_title, i );

        UpdateState2(data, i + 1);

        /* Decode previews */
        /* this will also detect more AC3 / DTS information */
        if( !DecodePreviews( data, title ) )
        {
            /* TODO: free things */
            hb_list_rem( data->title_set->list_title, title );
            for( j = 0; j < hb_list_count( title->list_audio ); j++)
            {
                audio = hb_list_item( title->list_audio, j );
                if ( audio->priv.scan_cache )
                {
                    hb_fifo_flush( audio->priv.scan_cache );
                    hb_fifo_close( &audio->priv.scan_cache );
                }
            }
            hb_title_close( &title );
            continue;
        }

        /* Make sure we found audio rates and bitrates */
        for( j = 0; j < hb_list_count( title->list_audio ); )
        {
            audio = hb_list_item( title->list_audio, j );
            if ( audio->priv.scan_cache )
            {
                hb_fifo_flush( audio->priv.scan_cache );
                hb_fifo_close( &audio->priv.scan_cache );
            }
            if( !audio->config.in.bitrate )
            {
                hb_log( "scan: removing audio 0x%x because no bitrate found",
                        audio->id );
                hb_list_rem( title->list_audio, audio );
                free( audio );
                continue;
            }
            j++;
        }

        if ( data->dvd || data->bd )
        {
            // The subtitle width and height needs to be set to the 
            // title widht and height for DVDs.  title width and
            // height don't get set until we decode previews, so
            // we can't set subtitle width/height till we get here.
            for( j = 0; j < hb_list_count( title->list_subtitle ); j++ )
            {
                hb_subtitle_t *subtitle = hb_list_item( title->list_subtitle, j );
                if ( subtitle->source == VOBSUB || subtitle->source == PGSSUB )
                {
                    subtitle->width = title->width;
                    subtitle->height = title->height;
                }
            }
        }
        i++;
    }

    data->title_set->feature = feature;

    /* Mark title scan complete and init jobs */
    for( i = 0; i < hb_list_count( data->title_set->list_title ); i++ )
    {
        title      = hb_list_item( data->title_set->list_title, i );
        title->flags |= HBTF_SCAN_COMPLETE;
#if defined(HB_TITLE_JOBS)
        title->job = hb_job_init( title );
#endif
    }

finish:

    if( data->bd )
    {
        hb_bd_close( &data->bd );
    }
    if( data->dvd )
    {
        hb_dvd_close( &data->dvd );
    }
    if (data->stream)
    {
        hb_stream_close(&data->stream);
    }
    if( data->batch )
    {
        hb_batch_close( &data->batch );
    }
    free( data->path );
    free( data );
    _data = NULL;
    hb_buffer_pool_free();
}