matroska_segment.cpp 48.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*****************************************************************************
 * mkv.cpp : matroska demuxer
 *****************************************************************************
 * Copyright (C) 2003-2004 the VideoLAN team
 * $Id$
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Steve Lhomme <steve.lhomme@free.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

25
#include "matroska_segment.hpp"
26

27
#include "chapters.hpp"
28

29
#include "demux.hpp"
30

31 32 33 34 35 36 37 38 39 40 41
/* Destructor */
matroska_segment_c::~matroska_segment_c()
{
    for( size_t i_track = 0; i_track < tracks.size(); i_track++ )
    {
        delete tracks[i_track]->p_compression_data;
        es_format_Clean( &tracks[i_track]->fmt );
        free( tracks[i_track]->p_extra_data );
        free( tracks[i_track]->psz_codec );
        delete tracks[i_track];
    }
42

43 44 45 46 47 48
    free( psz_writing_application );
    free( psz_muxing_application );
    free( psz_segment_filename );
    free( psz_title );
    free( psz_date_utc );
    free( p_indexes );
49

50 51 52 53 54
    delete ep;
    delete segment;
    delete p_segment_uid;
    delete p_prev_segment_uid;
    delete p_next_segment_uid;
55

56 57
    std::vector<chapter_edition_c*>::iterator index = stored_editions.begin();
    while ( index != stored_editions.end() )
58
    {
59 60
        delete (*index);
        index++;
61
    }
62 63
    std::vector<chapter_translation_c*>::iterator indext = translations.begin();
    while ( indext != translations.end() )
64
    {
65 66
        delete (*indext);
        indext++;
67
    }
68 69
    std::vector<KaxSegmentFamily*>::iterator indexf = families.begin();
    while ( indexf != families.end() )
70
    {
71 72 73
        delete (*indexf);
        indexf++;
   }
74 75
}

76

77
/*****************************************************************************
78 79 80 81 82 83 84
 * Tools
 *  * LoadCues : load the cues element and update index
 *
 *  * LoadTags : load ... the tags element
 *
 *  * InformationCreate : create all information, load tags if present
 *
85
 *****************************************************************************/
86
void matroska_segment_c::LoadCues( KaxCues *cues )
87
{
88 89 90
    EbmlParser  *ep;
    EbmlElement *el;
    size_t i, j;
91

92
    if( b_cues )
93
    {
94 95
        msg_Err( &sys.demuxer, "There can be only 1 Cues per section." );
        return;
96 97
    }

98 99 100 101 102 103
    ep = new EbmlParser( &es, cues, &sys.demuxer );
    while( ( el = ep->Get() ) != NULL )
    {
        if( MKV_IS_ID( el, KaxCuePoint ) )
        {
#define idx p_indexes[i_index]
104

105 106 107 108 109
            idx.i_track       = -1;
            idx.i_block_number= -1;
            idx.i_position    = -1;
            idx.i_time        = 0;
            idx.b_key         = true;
110

111 112 113 114 115 116
            ep->Down();
            while( ( el = ep->Get() ) != NULL )
            {
                if( MKV_IS_ID( el, KaxCueTime ) )
                {
                    KaxCueTime &ctime = *(KaxCueTime*)el;
117

118
                    ctime.ReadData( es.I_O() );
119

120 121 122 123 124 125 126 127 128 129
                    idx.i_time = uint64( ctime ) * i_timescale / (mtime_t)1000;
                }
                else if( MKV_IS_ID( el, KaxCueTrackPositions ) )
                {
                    ep->Down();
                    while( ( el = ep->Get() ) != NULL )
                    {
                        if( MKV_IS_ID( el, KaxCueTrack ) )
                        {
                            KaxCueTrack &ctrack = *(KaxCueTrack*)el;
130

131 132 133 134 135 136
                            ctrack.ReadData( es.I_O() );
                            idx.i_track = uint16( ctrack );
                        }
                        else if( MKV_IS_ID( el, KaxCueClusterPosition ) )
                        {
                            KaxCueClusterPosition &ccpos = *(KaxCueClusterPosition*)el;
137

138 139 140 141 142 143
                            ccpos.ReadData( es.I_O() );
                            idx.i_position = segment->GetGlobalPosition( uint64( ccpos ) );
                        }
                        else if( MKV_IS_ID( el, KaxCueBlockNumber ) )
                        {
                            KaxCueBlockNumber &cbnum = *(KaxCueBlockNumber*)el;
144

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
                            cbnum.ReadData( es.I_O() );
                            idx.i_block_number = uint32( cbnum );
                        }
                        else
                        {
                            msg_Dbg( &sys.demuxer, "         * Unknown (%s)", typeid(*el).name() );
                        }
                    }
                    ep->Up();
                }
                else
                {
                    msg_Dbg( &sys.demuxer, "     * Unknown (%s)", typeid(*el).name() );
                }
            }
            ep->Up();
161

162 163 164 165 166
#if 0
            msg_Dbg( &sys.demuxer, " * added time=%"PRId64" pos=%"PRId64
                     " track=%d bnum=%d", idx.i_time, idx.i_position,
                     idx.i_track, idx.i_block_number );
#endif
167

168 169 170 171 172 173 174
            i_index++;
            if( i_index >= i_index_max )
            {
                i_index_max += 1024;
                p_indexes = (mkv_index_t*)realloc( p_indexes, sizeof( mkv_index_t ) * i_index_max );
            }
#undef idx
175
        }
176
        else
177
        {
178
            msg_Dbg( &sys.demuxer, " * Unknown (%s)", typeid(*el).name() );
179 180
        }
    }
181 182 183 184
    delete ep;
    b_cues = true;
    msg_Dbg( &sys.demuxer, "|   - loading cues done." );
}
185

186
void matroska_segment_c::LoadTags( KaxTags *tags )
187
{
188 189 190
    EbmlParser  *ep;
    EbmlElement *el;
    size_t i, j;
191

192 193
    /* Master elements */
    ep = new EbmlParser( &es, tags, &sys.demuxer );
194

195
    while( ( el = ep->Get() ) != NULL )
196
    {
197
        if( MKV_IS_ID( el, KaxTag ) )
198
        {
199 200 201
            msg_Dbg( &sys.demuxer, "+ Tag" );
            ep->Down();
            while( ( el = ep->Get() ) != NULL )
202
            {
203
                if( MKV_IS_ID( el, KaxTagTargets ) )
204
                {
205 206 207 208 209 210 211
                    msg_Dbg( &sys.demuxer, "|   + Targets" );
                    ep->Down();
                    while( ( el = ep->Get() ) != NULL )
                    {
                        msg_Dbg( &sys.demuxer, "|   |   + Unknown (%s)", typeid( *el ).name() );
                    }
                    ep->Up();
212
                }
213
                else if( MKV_IS_ID( el, KaxTagGeneral ) )
214
                {
215 216 217 218 219 220 221
                    msg_Dbg( &sys.demuxer, "|   + General" );
                    ep->Down();
                    while( ( el = ep->Get() ) != NULL )
                    {
                        msg_Dbg( &sys.demuxer, "|   |   + Unknown (%s)", typeid( *el ).name() );
                    }
                    ep->Up();
222
                }
223
                else if( MKV_IS_ID( el, KaxTagGenres ) )
224
                {
225 226 227 228 229 230 231
                    msg_Dbg( &sys.demuxer, "|   + Genres" );
                    ep->Down();
                    while( ( el = ep->Get() ) != NULL )
                    {
                        msg_Dbg( &sys.demuxer, "|   |   + Unknown (%s)", typeid( *el ).name() );
                    }
                    ep->Up();
232
                }
233
                else if( MKV_IS_ID( el, KaxTagAudioSpecific ) )
234
                {
235 236 237 238 239 240 241
                    msg_Dbg( &sys.demuxer, "|   + Audio Specific" );
                    ep->Down();
                    while( ( el = ep->Get() ) != NULL )
                    {
                        msg_Dbg( &sys.demuxer, "|   |   + Unknown (%s)", typeid( *el ).name() );
                    }
                    ep->Up();
242
                }
243
                else if( MKV_IS_ID( el, KaxTagImageSpecific ) )
244
                {
245 246 247 248 249 250 251
                    msg_Dbg( &sys.demuxer, "|   + Images Specific" );
                    ep->Down();
                    while( ( el = ep->Get() ) != NULL )
                    {
                        msg_Dbg( &sys.demuxer, "|   |   + Unknown (%s)", typeid( *el ).name() );
                    }
                    ep->Up();
252
                }
253
                else if( MKV_IS_ID( el, KaxTagMultiComment ) )
254
                {
255 256 257
                    msg_Dbg( &sys.demuxer, "|   + Multi Comment" );
                }
                else if( MKV_IS_ID( el, KaxTagMultiCommercial ) )
258
                {
259
                    msg_Dbg( &sys.demuxer, "|   + Multi Commercial" );
260
                }
261
                else if( MKV_IS_ID( el, KaxTagMultiDate ) )
262
                {
263
                    msg_Dbg( &sys.demuxer, "|   + Multi Date" );
264
                }
265
                else if( MKV_IS_ID( el, KaxTagMultiEntity ) )
266
                {
267
                    msg_Dbg( &sys.demuxer, "|   + Multi Entity" );
268
                }
269
                else if( MKV_IS_ID( el, KaxTagMultiIdentifier ) )
270
                {
271
                    msg_Dbg( &sys.demuxer, "|   + Multi Identifier" );
272
                }
273
                else if( MKV_IS_ID( el, KaxTagMultiLegal ) )
274
                {
275
                    msg_Dbg( &sys.demuxer, "|   + Multi Legal" );
276
                }
277
                else if( MKV_IS_ID( el, KaxTagMultiTitle ) )
278
                {
279
                    msg_Dbg( &sys.demuxer, "|   + Multi Title" );
280 281 282
                }
                else
                {
283
                    msg_Dbg( &sys.demuxer, "|   + LoadTag Unknown (%s)", typeid( *el ).name() );
284 285
                }
            }
286
            ep->Up();
287 288 289
        }
        else
        {
290
            msg_Dbg( &sys.demuxer, "+ Unknown (%s)", typeid( *el ).name() );
291 292
        }
    }
293
    delete ep;
294

295
    msg_Dbg( &sys.demuxer, "loading tags done." );
296 297 298 299 300 301 302
}

/*****************************************************************************
 * InformationCreate:
 *****************************************************************************/
void matroska_segment_c::InformationCreate( )
{
303
    sys.meta = vlc_meta_New();
304

305 306 307
    if( psz_title )
    {
        vlc_meta_SetTitle( sys.meta, psz_title );
308
    }
309
    if( psz_date_utc )
310
    {
311 312 313 314 315 316 317 318 319 320 321 322 323 324
        vlc_meta_SetDate( sys.meta, psz_date_utc );
    }
#if 0
    if( psz_segment_filename )
    {
        fprintf( stderr, "***** WARNING: Unhandled meta - Use custom\n" );
    }
    if( psz_muxing_application )
    {
        fprintf( stderr, "***** WARNING: Unhandled meta - Use custom\n" );
    }
    if( psz_writing_application )
    {
        fprintf( stderr, "***** WARNING: Unhandled meta - Use custom\n" );
325 326
    }

327 328 329 330 331 332 333 334 335 336 337
    for( size_t i_track = 0; i_track < tracks.size(); i_track++ )
    {
//        mkv_track_t *tk = tracks[i_track];
//        vlc_meta_t *mtk = vlc_meta_New();
        fprintf( stderr, "***** WARNING: Unhandled child meta\n");
    }
#endif
#if 0
    if( i_tags_position >= 0 )
    {
        bool b_seekable;
338

339 340
        stream_Control( sys.demuxer.s, STREAM_CAN_FASTSEEK, &b_seekable );
        if( b_seekable )
341
        {
342
            LoadTags( );
343
        }
344 345 346
    }
#endif
}
347 348


349 350 351
/*****************************************************************************
 * Misc
 *****************************************************************************/
352

353
void matroska_segment_c::IndexAppendCluster( KaxCluster *cluster )
354
{
355 356 357 358 359 360
#define idx p_indexes[i_index]
    idx.i_track       = -1;
    idx.i_block_number= -1;
    idx.i_position    = cluster->GetElementPosition();
    idx.i_time        = -1;
    idx.b_key         = true;
361

362 363 364 365 366
    i_index++;
    if( i_index >= i_index_max )
    {
        i_index_max += 1024;
        p_indexes = (mkv_index_t*)realloc( p_indexes, sizeof( mkv_index_t ) * i_index_max );
367
    }
368
#undef idx
369 370
}

371 372

bool matroska_segment_c::PreloadFamily( const matroska_segment_c & of_segment )
373
{
374 375
    if ( b_preloaded )
        return false;
376

377
    for (size_t i=0; i<families.size(); i++)
378
    {
379
        for (size_t j=0; j<of_segment.families.size(); j++)
380
        {
381 382
            if ( *(families[i]) == *(of_segment.families[j]) )
                return Preload( );
383 384
        }
    }
385 386

    return false;
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
}

bool matroska_segment_c::CompareSegmentUIDs( const matroska_segment_c * p_item_a, const matroska_segment_c * p_item_b )
{
    EbmlBinary *p_tmp;

    if ( p_item_a == NULL || p_item_b == NULL )
        return false;

    p_tmp = (EbmlBinary *)p_item_a->p_segment_uid;
    if ( p_item_b->p_prev_segment_uid != NULL
          && *p_tmp == *p_item_b->p_prev_segment_uid )
        return true;

    p_tmp = (EbmlBinary *)p_item_a->p_next_segment_uid;
    if ( !p_tmp )
        return false;
 
    if ( p_item_b->p_segment_uid != NULL
          && *p_tmp == *p_item_b->p_segment_uid )
        return true;

    if ( p_item_b->p_prev_segment_uid != NULL
          && *p_tmp == *p_item_b->p_prev_segment_uid )
        return true;

    return false;
}

bool matroska_segment_c::Preload( )
{
    if ( b_preloaded )
        return false;

    EbmlElement *el = NULL;

    ep->Reset( &sys.demuxer );

    while( ( el = ep->Get() ) != NULL )
    {
        if( MKV_IS_ID( el, KaxSeekHead ) )
        {
            /* Multiple allowed */
            /* We bail at 10, to prevent possible recursion */
            msg_Dbg(  &sys.demuxer, "|   + Seek head" );
            if( i_seekhead_count < 10 )
            {
                i_seekhead_position = (int64_t) es.I_O().getFilePointer();
                ParseSeekHead( static_cast<KaxSeekHead*>( el ) );
            }
        }
        else if( MKV_IS_ID( el, KaxInfo ) )
        {
            /* Multiple allowed, mandatory */
            msg_Dbg(  &sys.demuxer, "|   + Information" );
            if( i_info_position < 0 ) // FIXME
                ParseInfo( static_cast<KaxInfo*>( el ) );
            i_info_position = (int64_t) es.I_O().getFilePointer();
        }
        else if( MKV_IS_ID( el, KaxTracks ) )
        {
            /* Multiple allowed */
            msg_Dbg(  &sys.demuxer, "|   + Tracks" );
            if( i_tracks_position < 0 ) // FIXME
                ParseTracks( static_cast<KaxTracks*>( el ) );
            if ( tracks.size() == 0 )
            {
                msg_Err( &sys.demuxer, "No tracks supported" );
                return false;
            }
            i_tracks_position = (int64_t) es.I_O().getFilePointer();
        }
        else if( MKV_IS_ID( el, KaxCues ) )
        {
            msg_Dbg(  &sys.demuxer, "|   + Cues" );
            if( i_cues_position < 0 )
                LoadCues( static_cast<KaxCues*>( el ) );
            i_cues_position = (int64_t) es.I_O().getFilePointer();
        }
        else if( MKV_IS_ID( el, KaxCluster ) )
        {
            msg_Dbg( &sys.demuxer, "|   + Cluster" );

            cluster = (KaxCluster*)el;

            i_cluster_pos = i_start_pos = cluster->GetElementPosition();
            ParseCluster( );

            ep->Down();
            /* stop pre-parsing the stream */
            break;
        }
        else if( MKV_IS_ID( el, KaxAttachments ) )
        {
            msg_Dbg( &sys.demuxer, "|   + Attachments" );
            if( i_attachments_position < 0 )
                ParseAttachments( static_cast<KaxAttachments*>( el ) );
            i_attachments_position = (int64_t) es.I_O().getFilePointer();
        }
        else if( MKV_IS_ID( el, KaxChapters ) )
        {
            msg_Dbg( &sys.demuxer, "|   + Chapters" );
            if( i_chapters_position < 0 )
                ParseChapters( static_cast<KaxChapters*>( el ) );
            i_chapters_position = (int64_t) es.I_O().getFilePointer();
        }
        else if( MKV_IS_ID( el, KaxTag ) )
        {
            msg_Dbg( &sys.demuxer, "|   + Tags" );
            if( i_tags_position < 0) // FIXME
                ;//LoadTags( static_cast<KaxTags*>( el ) );
            i_tags_position = (int64_t) es.I_O().getFilePointer();
        }
        else
            msg_Dbg( &sys.demuxer, "|   + Preload Unknown (%s)", typeid(*el).name() );
    }

    b_preloaded = true;

    return true;
}

/* Here we try to load elements that were found in Seek Heads, but not yet parsed */
bool matroska_segment_c::LoadSeekHeadItem( const EbmlCallbacks & ClassInfos, int64_t i_element_position )
{
    int64_t     i_sav_position = (int64_t)es.I_O().getFilePointer();
    EbmlElement *el;

    es.I_O().setFilePointer( i_element_position, seek_beginning );
    el = es.FindNextID( ClassInfos, 0xFFFFFFFFL);

    if( el == NULL )
    {
        msg_Err( &sys.demuxer, "cannot load some cues/chapters/tags etc. (broken seekhead or file)" );
        es.I_O().setFilePointer( i_sav_position, seek_beginning );
        return false;
    }

    if( MKV_IS_ID( el, KaxSeekHead ) )
    {
        /* Multiple allowed */
        msg_Dbg( &sys.demuxer, "|   + Seek head" );
        if( i_seekhead_count < 10 )
        {
            i_seekhead_position = i_element_position;
            ParseSeekHead( static_cast<KaxSeekHead*>( el ) );
        }
    }
    else if( MKV_IS_ID( el, KaxInfo ) ) // FIXME
    {
        /* Multiple allowed, mandatory */
        msg_Dbg( &sys.demuxer, "|   + Information" );
        if( i_info_position < 0 )
            ParseInfo( static_cast<KaxInfo*>( el ) );
        i_info_position = i_element_position;
    }
    else if( MKV_IS_ID( el, KaxTracks ) ) // FIXME
    {
        /* Multiple allowed */
        msg_Dbg( &sys.demuxer, "|   + Tracks" );
        if( i_tracks_position < 0 )
            ParseTracks( static_cast<KaxTracks*>( el ) );
        if ( tracks.size() == 0 )
        {
            msg_Err( &sys.demuxer, "No tracks supported" );
            delete el;
            es.I_O().setFilePointer( i_sav_position, seek_beginning );
            return false;
        }
        i_tracks_position = i_element_position;
    }
    else if( MKV_IS_ID( el, KaxCues ) )
    {
        msg_Dbg( &sys.demuxer, "|   + Cues" );
        if( i_cues_position < 0 )
            LoadCues( static_cast<KaxCues*>( el ) );
        i_cues_position = i_element_position;
    }
    else if( MKV_IS_ID( el, KaxAttachments ) )
    {
        msg_Dbg( &sys.demuxer, "|   + Attachments" );
        if( i_attachments_position < 0 )
            ParseAttachments( static_cast<KaxAttachments*>( el ) );
        i_attachments_position = i_element_position;
    }
    else if( MKV_IS_ID( el, KaxChapters ) )
    {
        msg_Dbg( &sys.demuxer, "|   + Chapters" );
        if( i_chapters_position < 0 )
            ParseChapters( static_cast<KaxChapters*>( el ) );
        i_chapters_position = i_element_position;
    }
    else if( MKV_IS_ID( el, KaxTag ) ) // FIXME
    {
        msg_Dbg( &sys.demuxer, "|   + Tags" );
        if( i_tags_position < 0 )
            ;//LoadTags( static_cast<KaxTags*>( el ) );
        i_tags_position = i_element_position;
    }
    else
    {
        msg_Dbg( &sys.demuxer, "|   + LoadSeekHeadItem Unknown (%s)", typeid(*el).name() );
    }
    delete el;

    es.I_O().setFilePointer( i_sav_position, seek_beginning );
    return true;
}

596 597
int matroska_segment_c::BlockFindTrackIndex( size_t *pi_track,
                                             const KaxBlock *p_block, const KaxSimpleBlock *p_simpleblock )
598
{
599 600 601
    size_t          i_track;
    unsigned int    i;
    bool            b;
602

603
    for( i_track = 0; i_track < tracks.size(); i_track++ )
604
    {
605
        const mkv_track_t *tk = tracks[i_track];
606

607 608
        if( ( p_block != NULL && tk->i_number == p_block->TrackNum() ) ||
            ( p_simpleblock != NULL && tk->i_number == p_simpleblock->TrackNum() ) )
609 610 611 612 613
        {
            break;
        }
    }

614 615
    if( i_track >= tracks.size() )
        return VLC_EGENERIC;
616

617 618 619
    if( pi_track )
        *pi_track = i_track;
    return VLC_SUCCESS;
620 621
}

622
bool matroska_segment_c::Select( mtime_t i_start_time )
623
{
624 625 626 627 628
    size_t i_track;

    /* add all es */
    msg_Dbg( &sys.demuxer, "found %d es", (int)tracks.size() );
    sys.b_pci_packet_set = false;
629

630
    for( i_track = 0; i_track < tracks.size(); i_track++ )
631
    {
632
        if( tracks[i_track]->fmt.i_cat == UNKNOWN_ES )
633
        {
634 635 636
            msg_Warn( &sys.demuxer, "invalid track[%d, n=%d]", (int)i_track, tracks[i_track]->i_number );
            tracks[i_track]->p_es = NULL;
            continue;
637 638
        }

639
        if( !strcmp( tracks[i_track]->psz_codec, "V_MS/VFW/FOURCC" ) )
640
        {
641
            if( tracks[i_track]->i_extra_data < (int)sizeof( BITMAPINFOHEADER ) )
642
            {
643 644
                msg_Err( &sys.demuxer, "missing/invalid BITMAPINFOHEADER" );
                tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
645
            }
646 647 648
            else
            {
                BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)tracks[i_track]->p_extra_data;
649

650 651 652
                tracks[i_track]->fmt.video.i_width = GetDWLE( &p_bih->biWidth );
                tracks[i_track]->fmt.video.i_height= GetDWLE( &p_bih->biHeight );
                tracks[i_track]->fmt.i_codec       = GetFOURCC( &p_bih->biCompression );
653

654 655 656 657 658 659
                tracks[i_track]->fmt.i_extra       = GetDWLE( &p_bih->biSize ) - sizeof( BITMAPINFOHEADER );
                if( tracks[i_track]->fmt.i_extra > 0 )
                {
                    tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->fmt.i_extra );
                    memcpy( tracks[i_track]->fmt.p_extra, &p_bih[1], tracks[i_track]->fmt.i_extra );
                }
660 661
            }
        }
662 663
        else if( !strcmp( tracks[i_track]->psz_codec, "V_MPEG1" ) ||
                 !strcmp( tracks[i_track]->psz_codec, "V_MPEG2" ) )
664
        {
665
            tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' );
666
        }
667
        else if( !strncmp( tracks[i_track]->psz_codec, "V_THEORA", 8 ) )
668
        {
669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735
            uint8_t *p_data = tracks[i_track]->p_extra_data;
            tracks[i_track]->fmt.i_codec = VLC_FOURCC( 't', 'h', 'e', 'o' );
            if( tracks[i_track]->i_extra_data >= 4 ) {
                if( p_data[0] == 2 ) {
                    int i = 1;
                    int i_size1 = 0, i_size2 = 0;
                    p_data++;
                    /* read size of first header packet */
                    while( *p_data == 0xFF &&
                           i < tracks[i_track]->i_extra_data )
                    {
                        i_size1 += *p_data;
                        p_data++;
                        i++;
                    }
                    i_size1 += *p_data;
                    p_data++;
                    i++;
                    msg_Dbg( &sys.demuxer, "first theora header size %d", i_size1 );
                    /* read size of second header packet */
                    while( *p_data == 0xFF &&
                           i < tracks[i_track]->i_extra_data )
                    {
                        i_size2 += *p_data;
                        p_data++;
                        i++;
                    }
                    i_size2 += *p_data;
                    p_data++;
                    i++;
                    int i_size3 = tracks[i_track]->i_extra_data - i - i_size1
                        - i_size2;
                    msg_Dbg( &sys.demuxer, "second theora header size %d", i_size2 );
                    msg_Dbg( &sys.demuxer, "third theora header size %d", i_size3 );
                    tracks[i_track]->fmt.i_extra = i_size1 + i_size2 + i_size3
                        + 6;
                    if( i_size1 > 0 && i_size2 > 0 && i_size3 > 0  ) {
                        tracks[i_track]->fmt.p_extra =
                            malloc( tracks[i_track]->fmt.i_extra );
                        uint8_t *p_out = (uint8_t*)tracks[i_track]->fmt.p_extra;
                        *p_out++ = (i_size1>>8) & 0xFF;
                        *p_out++ = i_size1 & 0xFF;
                        memcpy( p_out, p_data, i_size1 );
                        p_data += i_size1;
                        p_out += i_size1;
 
                        *p_out++ = (i_size2>>8) & 0xFF;
                        *p_out++ = i_size2 & 0xFF;
                        memcpy( p_out, p_data, i_size2 );
                        p_data += i_size2;
                        p_out += i_size2;

                        *p_out++ = (i_size3>>8) & 0xFF;
                        *p_out++ = i_size3 & 0xFF;
                        memcpy( p_out, p_data, i_size3 );
                        p_data += i_size3;
                        p_out += i_size3;
                    }
                    else
                    {
                        msg_Err( &sys.demuxer, "inconsistant theora extradata" );
                    }
                }
                else {
                    msg_Err( &sys.demuxer, "Wrong number of ogg packets with theora headers (%d)", p_data[0] + 1 );
                }
            }
736
        }
737
        else if( !strncmp( tracks[i_track]->psz_codec, "V_REAL/RV", 9 ) )
738
        {
739 740 741 742 743 744 745 746
            if( !strcmp( tracks[i_track]->psz_codec, "V_REAL/RV10" ) )
                tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'R', 'V', '1', '0' );
            else if( !strcmp( tracks[i_track]->psz_codec, "V_REAL/RV20" ) )
                tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'R', 'V', '2', '0' );
            else if( !strcmp( tracks[i_track]->psz_codec, "V_REAL/RV30" ) )
                tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'R', 'V', '3', '0' );
            else if( !strcmp( tracks[i_track]->psz_codec, "V_REAL/RV40" ) )
                tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'R', 'V', '4', '0' );
747
        }
748
        else if( !strncmp( tracks[i_track]->psz_codec, "V_MPEG4", 7 ) )
749
        {
750 751 752 753 754
            if( !strcmp( tracks[i_track]->psz_codec, "V_MPEG4/MS/V3" ) )
            {
                tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'D', 'I', 'V', '3' );
            }
            else if( !strncmp( tracks[i_track]->psz_codec, "V_MPEG4/ISO", 11 ) )
755
            {
756 757 758 759 760 761 762 763
                /* A MPEG 4 codec, SP, ASP, AP or AVC */
                if( !strcmp( tracks[i_track]->psz_codec, "V_MPEG4/ISO/AVC" ) )
                    tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'a', 'v', 'c', '1' );
                else
                    tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' );
                tracks[i_track]->fmt.i_extra = tracks[i_track]->i_extra_data;
                tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->i_extra_data );
                memcpy( tracks[i_track]->fmt.p_extra,tracks[i_track]->p_extra_data, tracks[i_track]->i_extra_data );
764 765
            }
        }
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
        else if( !strcmp( tracks[i_track]->psz_codec, "V_QUICKTIME" ) )
        {
            MP4_Box_t *p_box = (MP4_Box_t*)malloc( sizeof( MP4_Box_t ) );
            stream_t *p_mp4_stream = stream_MemoryNew( VLC_OBJECT(&sys.demuxer),
                                                       tracks[i_track]->p_extra_data,
                                                       tracks[i_track]->i_extra_data,
                                                       true );
            MP4_ReadBoxCommon( p_mp4_stream, p_box );
            MP4_ReadBox_sample_vide( p_mp4_stream, p_box );
            tracks[i_track]->fmt.i_codec = p_box->i_type;
            tracks[i_track]->fmt.video.i_width = p_box->data.p_sample_vide->i_width;
            tracks[i_track]->fmt.video.i_height = p_box->data.p_sample_vide->i_height;
            tracks[i_track]->fmt.i_extra = p_box->data.p_sample_vide->i_qt_image_description;
            tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->fmt.i_extra );
            memcpy( tracks[i_track]->fmt.p_extra, p_box->data.p_sample_vide->p_qt_image_description, tracks[i_track]->fmt.i_extra );
            MP4_FreeBox_sample_vide( p_box );
            stream_Delete( p_mp4_stream );
        }
        else if( !strcmp( tracks[i_track]->psz_codec, "A_MS/ACM" ) )
785
        {
786
            if( tracks[i_track]->i_extra_data < (int)sizeof( WAVEFORMATEX ) )
787
            {
788 789
                msg_Err( &sys.demuxer, "missing/invalid WAVEFORMATEX" );
                tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
790
            }
791
            else
792
            {
793
                WAVEFORMATEX *p_wf = (WAVEFORMATEX*)tracks[i_track]->p_extra_data;
794

795
                wf_tag_to_fourcc( GetWLE( &p_wf->wFormatTag ), &tracks[i_track]->fmt.i_codec, NULL );
796

797 798 799 800 801
                tracks[i_track]->fmt.audio.i_channels   = GetWLE( &p_wf->nChannels );
                tracks[i_track]->fmt.audio.i_rate = GetDWLE( &p_wf->nSamplesPerSec );
                tracks[i_track]->fmt.i_bitrate    = GetDWLE( &p_wf->nAvgBytesPerSec ) * 8;
                tracks[i_track]->fmt.audio.i_blockalign = GetWLE( &p_wf->nBlockAlign );;
                tracks[i_track]->fmt.audio.i_bitspersample = GetWLE( &p_wf->wBitsPerSample );
802

803 804 805 806 807 808 809
                tracks[i_track]->fmt.i_extra            = GetWLE( &p_wf->cbSize );
                if( tracks[i_track]->fmt.i_extra > 0 )
                {
                    tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->fmt.i_extra );
                    memcpy( tracks[i_track]->fmt.p_extra, &p_wf[1], tracks[i_track]->fmt.i_extra );
                }
            }
810
        }
811 812 813
        else if( !strcmp( tracks[i_track]->psz_codec, "A_MPEG/L3" ) ||
                 !strcmp( tracks[i_track]->psz_codec, "A_MPEG/L2" ) ||
                 !strcmp( tracks[i_track]->psz_codec, "A_MPEG/L1" ) )
814
        {
815
            tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
816
        }
817
        else if( !strcmp( tracks[i_track]->psz_codec, "A_AC3" ) )
818
        {
819
            tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
820
        }
821
        else if( !strcmp( tracks[i_track]->psz_codec, "A_EAC3" ) )
822
        {
823
            tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'e', 'a', 'c', '3' );
824
        }
825
        else if( !strcmp( tracks[i_track]->psz_codec, "A_DTS" ) )
826
        {
827
            tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'd', 't', 's', ' ' );
828
        }
829
        else if( !strcmp( tracks[i_track]->psz_codec, "A_FLAC" ) )
830
        {
831 832 833 834
            tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'f', 'l', 'a', 'c' );
            tracks[i_track]->fmt.i_extra = tracks[i_track]->i_extra_data;
            tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->i_extra_data );
            memcpy( tracks[i_track]->fmt.p_extra,tracks[i_track]->p_extra_data, tracks[i_track]->i_extra_data );
835
        }
836
        else if( !strcmp( tracks[i_track]->psz_codec, "A_VORBIS" ) )
837
        {
838 839
            int i, i_offset = 1, i_size[3], i_extra;
            uint8_t *p_extra;
840

841
            tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'v', 'o', 'r', 'b' );
842

843 844 845
            /* Split the 3 headers */
            if( tracks[i_track]->p_extra_data[0] != 0x02 )
                msg_Err( &sys.demuxer, "invalid vorbis header" );
846

847
            for( i = 0; i < 2; i++ )
848
            {
849 850
                i_size[i] = 0;
                while( i_offset < tracks[i_track]->i_extra_data )
851
                {
852 853
                    i_size[i] += tracks[i_track]->p_extra_data[i_offset];
                    if( tracks[i_track]->p_extra_data[i_offset++] != 0xff ) break;
854 855 856
                }
            }

857 858 859
            i_size[0] = __MIN(i_size[0], tracks[i_track]->i_extra_data - i_offset);
            i_size[1] = __MIN(i_size[1], tracks[i_track]->i_extra_data -i_offset -i_size[0]);
            i_size[2] = tracks[i_track]->i_extra_data - i_offset - i_size[0] - i_size[1];
860

861 862 863 864
            tracks[i_track]->fmt.i_extra = 3 * 2 + i_size[0] + i_size[1] + i_size[2];
            tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->fmt.i_extra );
            p_extra = (uint8_t *)tracks[i_track]->fmt.p_extra; i_extra = 0;
            for( i = 0; i < 3; i++ )
865
            {
866 867 868 869 870 871
                *(p_extra++) = i_size[i] >> 8;
                *(p_extra++) = i_size[i] & 0xFF;
                memcpy( p_extra, tracks[i_track]->p_extra_data + i_offset + i_extra,
                        i_size[i] );
                p_extra += i_size[i];
                i_extra += i_size[i];
872 873
            }
        }
874 875
        else if( !strncmp( tracks[i_track]->psz_codec, "A_AAC/MPEG2/", strlen( "A_AAC/MPEG2/" ) ) ||
                 !strncmp( tracks[i_track]->psz_codec, "A_AAC/MPEG4/", strlen( "A_AAC/MPEG4/" ) ) )
876
        {
877 878
            int i_profile, i_srate, sbr = 0;
            static const unsigned int i_sample_rates[] =
879
            {
880 881 882
                    96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
                        16000, 12000, 11025, 8000,  7350,  0,     0,     0
            };
883

884 885
            tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
            /* create data for faad (MP4DecSpecificDescrTag)*/
886

887
            if( !strcmp( &tracks[i_track]->psz_codec[12], "MAIN" ) )
888
            {
889
                i_profile = 0;
890
            }
891
            else if( !strcmp( &tracks[i_track]->psz_codec[12], "LC" ) )
892
            {
893
                i_profile = 1;
894
            }
895
            else if( !strcmp( &tracks[i_track]->psz_codec[12], "SSR" ) )
896
            {
897
                i_profile = 2;
898
            }
899
            else if( !strcmp( &tracks[i_track]->psz_codec[12], "LC/SBR" ) )
900
            {
901 902
                i_profile = 1;
                sbr = 1;
903
            }
904
            else
905
            {
906
                i_profile = 3;
907
            }
908 909

            for( i_srate = 0; i_srate < 13; i_srate++ )
910
            {
911 912 913 914
                if( i_sample_rates[i_srate] == tracks[i_track]->i_original_rate )
                {
                    break;
                }
915
            }
916 917 918 919 920 921 922
            msg_Dbg( &sys.demuxer, "profile=%d srate=%d", i_profile, i_srate );

            tracks[i_track]->fmt.i_extra = sbr ? 5 : 2;
            tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->fmt.i_extra );
            ((uint8_t*)tracks[i_track]->fmt.p_extra)[0] = ((i_profile + 1) << 3) | ((i_srate&0xe) >> 1);
            ((uint8_t*)tracks[i_track]->fmt.p_extra)[1] = ((i_srate & 0x1) << 7) | (tracks[i_track]->fmt.audio.i_channels << 3);
            if (sbr != 0)
923
            {
924 925 926 927 928 929 930 931
                int syncExtensionType = 0x2B7;
                int iDSRI;
                for (iDSRI=0; iDSRI<13; iDSRI++)
                    if( i_sample_rates[iDSRI] == tracks[i_track]->fmt.audio.i_rate )
                        break;
                ((uint8_t*)tracks[i_track]->fmt.p_extra)[2] = (syncExtensionType >> 3) & 0xFF;
                ((uint8_t*)tracks[i_track]->fmt.p_extra)[3] = ((syncExtensionType & 0x7) << 5) | 5;
                ((uint8_t*)tracks[i_track]->fmt.p_extra)[4] = ((1 & 0x1) << 7) | (iDSRI << 3);
932 933
            }
        }
934
        else if( !strcmp( tracks[i_track]->psz_codec, "A_AAC" ) )
935
        {
936 937 938 939
            tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
            tracks[i_track]->fmt.i_extra = tracks[i_track]->i_extra_data;
            tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->i_extra_data );
            memcpy( tracks[i_track]->fmt.p_extra, tracks[i_track]->p_extra_data, tracks[i_track]->i_extra_data );
940
        }
941
        else if( !strcmp( tracks[i_track]->psz_codec, "A_WAVPACK4" ) )
942
        {
943 944 945 946
            tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'W', 'V', 'P', 'K' );
            tracks[i_track]->fmt.i_extra = tracks[i_track]->i_extra_data;
            tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->i_extra_data );
            memcpy( tracks[i_track]->fmt.p_extra, tracks[i_track]->p_extra_data, tracks[i_track]->i_extra_data );
947
        }
948
        else if( !strcmp( tracks[i_track]->psz_codec, "A_TTA1" ) )
949
        {
950 951 952 953
            tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'T', 'T', 'A', '1' );
            tracks[i_track]->fmt.i_extra = tracks[i_track]->i_extra_data;
            tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->i_extra_data );
            memcpy( tracks[i_track]->fmt.p_extra, tracks[i_track]->p_extra_data, tracks[i_track]->i_extra_data );
954
        }
955 956 957
        else if( !strcmp( tracks[i_track]->psz_codec, "A_PCM/INT/BIG" ) ||
                 !strcmp( tracks[i_track]->psz_codec, "A_PCM/INT/LIT" ) ||
                 !strcmp( tracks[i_track]->psz_codec, "A_PCM/FLOAT/IEEE" ) )
958
        {
959 960 961
            if( !strcmp( tracks[i_track]->psz_codec, "A_PCM/INT/BIG" ) )
            {
                tracks[i_track]->fmt.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );
962
            }
963 964 965 966 967
            else
            {
                tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
            }
            tracks[i_track]->fmt.audio.i_blockalign = ( tracks[i_track]->fmt.audio.i_bitspersample + 7 ) / 8 * tracks[i_track]->fmt.audio.i_channels;
968
        }
969 970
        /* disabled due to the potential "S_KATE" namespace issue */
        else if( !strcmp( tracks[i_track]->psz_codec, "S_KATE" ) )
Jean-Baptiste Kempf's avatar