⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp4.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 4 页
字号:
        p_data  = block_FifoGet( p_input->p_fifo );        if( p_stream->fmt.i_codec == VLC_FOURCC( 'h', '2', '6', '4' ) )        {            ConvertAVC1( p_mux, p_stream, p_data );        }        else if( p_stream->fmt.i_codec == VLC_FOURCC( 's', 'u', 'b', 't' ) )        {            p_data = ConvertSUBT( p_mux, p_stream, p_data );        }        if( p_stream->fmt.i_cat != SPU_ES )        {            /* Fix length of the sample */            if( p_input->p_fifo->i_depth > 0 )            {                block_t *p_next = block_FifoShow( p_input->p_fifo );                int64_t       i_diff  = p_next->i_dts - p_data->i_dts;                if( i_diff < I64C(1000000 ) )   /* protection */                {                    p_data->i_length = i_diff;                }            }            if( p_data->i_length <= 0 )            {                msg_Warn( p_mux, "i_length <= 0" );                p_stream->i_length_neg += p_data->i_length - 1;                p_data->i_length = 1;            }            else if( p_stream->i_length_neg < 0 )            {                int64_t i_recover = __MIN( p_data->i_length / 4, - p_stream->i_length_neg );                p_data->i_length -= i_recover;                p_stream->i_length_neg += i_recover;            }        }        /* Save starting time */        if( p_stream->i_entry_count == 0 )        {            p_stream->i_dts_start = p_data->i_dts;            /* Update global dts_start */            if( p_sys->i_dts_start <= 0 ||                p_stream->i_dts_start < p_sys->i_dts_start )            {                p_sys->i_dts_start = p_stream->i_dts_start;            }        }        if( p_stream->fmt.i_cat == SPU_ES && p_stream->i_entry_count > 0 )        {            int64_t i_length = p_data->i_dts - p_stream->i_last_dts;            if( i_length <= 0 )            {                /* FIXME handle this broken case */                i_length = 1;            }            /* Fix last entry */            if( p_stream->entry[p_stream->i_entry_count-1].i_length <= 0 )            {                p_stream->entry[p_stream->i_entry_count-1].i_length = i_length;            }        }        /* add index entry */        p_stream->entry[p_stream->i_entry_count].i_pos    = p_sys->i_pos;        p_stream->entry[p_stream->i_entry_count].i_size   = p_data->i_buffer;        p_stream->entry[p_stream->i_entry_count].i_pts_dts=            __MAX( p_data->i_pts - p_data->i_dts, 0 );        p_stream->entry[p_stream->i_entry_count].i_length = p_data->i_length;        p_stream->entry[p_stream->i_entry_count].i_flags  = p_data->i_flags;        p_stream->i_entry_count++;        /* XXX: -1 to always have 2 entry for easy adding of empty SPU */        if( p_stream->i_entry_count >= p_stream->i_entry_max - 1 )        {            p_stream->i_entry_max += 1000;            p_stream->entry =                realloc( p_stream->entry,                         p_stream->i_entry_max * sizeof( mp4_entry_t ) );        }        /* update */        p_stream->i_duration += p_data->i_length;        p_sys->i_pos += p_data->i_buffer;        /* Save the DTS */        p_stream->i_last_dts = p_data->i_dts;        /* write data */        sout_AccessOutWrite( p_mux->p_access, p_data );        if( p_stream->fmt.i_cat == SPU_ES )        {            int64_t i_length = p_stream->entry[p_stream->i_entry_count-1].i_length;            if( i_length != 0 )            {                /* TODO */                msg_Dbg( p_mux, "writing a empty subs" ) ;                /* Append a idx entry */                p_stream->entry[p_stream->i_entry_count].i_pos    = p_sys->i_pos;                p_stream->entry[p_stream->i_entry_count].i_size   = 3;                p_stream->entry[p_stream->i_entry_count].i_pts_dts= 0;                p_stream->entry[p_stream->i_entry_count].i_length = 0;                p_stream->entry[p_stream->i_entry_count].i_flags  = 0;                /* XXX: No need to grow the entry here */                p_stream->i_entry_count++;                /* Fix last dts */                p_stream->i_last_dts += i_length;                /* Write a " " */                p_data = block_New( p_mux, 3 );                p_data->p_buffer[0] = 0;                p_data->p_buffer[1] = 1;                p_data->p_buffer[2] = ' ';                p_sys->i_pos += p_data->i_buffer;                sout_AccessOutWrite( p_mux->p_access, p_data );            }            /* Fix duration */            p_stream->i_duration = p_stream->i_last_dts - p_stream->i_dts_start;        }    }    return( VLC_SUCCESS );}/***************************************************************************** * *****************************************************************************/static block_t *ConvertSUBT( sout_mux_t *p_mux, mp4_stream_t *tk, block_t *p_block ){    p_block = block_Realloc( p_block, 2, p_block->i_buffer );    /* No trailling '\0' */    if( p_block->i_buffer > 2 && p_block->p_buffer[p_block->i_buffer-1] == '\0' )        p_block->i_buffer--;    p_block->p_buffer[0] = ( (p_block->i_buffer - 2) >> 8 )&0xff;    p_block->p_buffer[1] = ( (p_block->i_buffer - 2)      )&0xff;    return p_block;}static void ConvertAVC1( sout_mux_t *p_mux, mp4_stream_t *tk, block_t *p_block ){    uint8_t *last = p_block->p_buffer;  /* Assume it starts with 0x00000001 */    uint8_t *dat  = &p_block->p_buffer[4];    uint8_t *end = &p_block->p_buffer[p_block->i_buffer];    /* Replace the 4 bytes start code with 4 bytes size,     * FIXME are all startcode 4 bytes ? (I don't think :( */    while( dat < end )    {        int i_size;        while( dat < end - 4 )        {            if( dat[0] == 0x00 && dat[1] == 0x00  &&                dat[2] == 0x00 && dat[3] == 0x01 )            {                break;            }            dat++;        }        if( dat >= end - 4 )        {            dat = end;        }        /* Fix size */        i_size = dat - &last[4];        last[0] = ( i_size >> 24 )&0xff;        last[1] = ( i_size >> 16 )&0xff;        last[2] = ( i_size >>  8 )&0xff;        last[3] = ( i_size       )&0xff;        if( (last[4]&0x1f) == 7 && tk->avc.i_sps <= 0 )  /* SPS */        {            tk->avc.i_sps = i_size;            tk->avc.sps = malloc( i_size );            memcpy( tk->avc.sps, &last[4], i_size );            tk->avc.i_profile = tk->avc.sps[1];            tk->avc.i_level   = tk->avc.sps[3];        }        else if( (last[4]&0x1f) == 8 && tk->avc.i_pps <= 0 )   /* PPS */        {            tk->avc.i_pps = i_size;            tk->avc.pps = malloc( i_size );            memcpy( tk->avc.pps, &last[4], i_size );        }        last = dat;        dat += 4;    }}static int GetDescrLength( int i_size ){    if( i_size < 0x00000080 )        return 2 + i_size;    else if( i_size < 0x00004000 )        return 3 + i_size;    else if( i_size < 0x00200000 )        return 4 + i_size;    else        return 5 + i_size;}static bo_t *GetESDS( mp4_stream_t *p_stream ){    bo_t *esds;    int  i_stream_type;    int  i_object_type_indication;    int  i_decoder_specific_info_size;    unsigned int i;    int64_t i_bitrate_avg = 0;    int64_t i_bitrate_max = 0;    /* Compute avg/max bitrate */    for( i = 0; i < p_stream->i_entry_count; i++ )    {        i_bitrate_avg += p_stream->entry[i].i_size;        if( p_stream->entry[i].i_length > 0)        {            int64_t i_bitrate = I64C(8000000) * p_stream->entry[i].i_size / p_stream->entry[i].i_length;            if( i_bitrate > i_bitrate_max )                i_bitrate_max = i_bitrate;        }    }    if( p_stream->i_duration > 0 )        i_bitrate_avg = I64C(8000000) * i_bitrate_avg / p_stream->i_duration;    else        i_bitrate_avg = 0;    if( i_bitrate_max <= 1 )        i_bitrate_max = 0x7fffffff;    /* */    if( p_stream->fmt.i_extra > 0 )    {        i_decoder_specific_info_size =            GetDescrLength( p_stream->fmt.i_extra );    }    else    {        i_decoder_specific_info_size = 0;    }    esds = box_full_new( "esds", 0, 0 );    /* ES_Descr */    bo_add_descr( esds, 0x03, 3 +                  GetDescrLength( 13 + i_decoder_specific_info_size ) +                  GetDescrLength( 1 ) );    bo_add_16be( esds, p_stream->i_track_id );    bo_add_8   ( esds, 0x1f );      // flags=0|streamPriority=0x1f    /* DecoderConfigDescr */    bo_add_descr( esds, 0x04, 13 + i_decoder_specific_info_size );    switch( p_stream->fmt.i_codec )    {        case VLC_FOURCC( 'm', 'p', '4', 'v' ):            i_object_type_indication = 0x20;            break;        case VLC_FOURCC( 'm', 'p', 'g', 'v' ):            /* FIXME MPEG-I=0x6b, MPEG-II = 0x60 -> 0x65 */            i_object_type_indication = 0x60;            break;        case VLC_FOURCC( 'm', 'p', '4', 'a' ):            /* FIXME for mpeg2-aac == 0x66->0x68 */            i_object_type_indication = 0x40;            break;        case VLC_FOURCC( 'm', 'p', 'g', 'a' ):            i_object_type_indication =                p_stream->fmt.audio.i_rate < 32000 ? 0x69 : 0x6b;            break;        default:            i_object_type_indication = 0x00;            break;    }    i_stream_type = p_stream->fmt.i_cat == VIDEO_ES ? 0x04 : 0x05;    bo_add_8   ( esds, i_object_type_indication );    bo_add_8   ( esds, ( i_stream_type << 2 ) | 1 );    bo_add_24be( esds, 1024 * 1024 );       // bufferSizeDB    bo_add_32be( esds, i_bitrate_max );     // maxBitrate    bo_add_32be( esds, i_bitrate_avg );     // avgBitrate    if( p_stream->fmt.i_extra > 0 )    {        int i;        /* DecoderSpecificInfo */        bo_add_descr( esds, 0x05, p_stream->fmt.i_extra );        for( i = 0; i < p_stream->fmt.i_extra; i++ )        {            bo_add_8( esds, ((uint8_t*)p_stream->fmt.p_extra)[i] );        }    }    /* SL_Descr mandatory */    bo_add_descr( esds, 0x06, 1 );    bo_add_8    ( esds, 0x02 );  // sl_predefined    box_fix( esds );    return esds;}static bo_t *GetWaveTag( mp4_stream_t *p_stream ){    bo_t *wave;    bo_t *box;    wave = box_new( "wave" );    box = box_new( "frma" );    bo_add_fourcc( box, "mp4a" );    box_fix( box );    box_gather( wave, box );    box = box_new( "mp4a" );    bo_add_32be( box, 0 );    box_fix( box );    box_gather( wave, box );    box = GetESDS( p_stream );    box_fix( box );    box_gather( wave, box );    box = box_new( "srcq" );    bo_add_32be( box, 0x40 );    box_fix( box );    box_gather( wave, box );    /* wazza ? */    bo_add_32be( wave, 8 ); /* new empty box */    bo_add_32be( wave, 0 ); /* box label */    box_fix( wave );    return wave;}static bo_t *GetAvcCTag( mp4_stream_t *p_stream ){    bo_t *avcC;    /* FIXME use better value */    avcC = box_new( "avcC" );    bo_add_8( avcC, 1 );      /* configuration version */    bo_add_8( avcC, p_stream->avc.i_profile );    bo_add_8( avcC, p_stream->avc.i_profile );     /* profile compatible ??? */    bo_add_8( avcC, p_stream->avc.i_level );       /* level, 5.1 */    bo_add_8( avcC, 0xff );   /* 0b11111100 | lengthsize = 0x11 */    bo_add_8( avcC, 0xe0 | (p_stream->avc.i_sps > 0 ? 1 : 0) );   /* 0b11100000 | sps_count */    if( p_stream->avc.i_sps > 0 )    {        bo_add_16be( avcC, p_stream->avc.i_sps );        bo_add_mem( avcC, p_stream->avc.i_sps, p_stream->avc.sps );    }    bo_add_8( avcC, (p_stream->avc.i_pps > 0 ? 1 : 0) );   /* pps_count */    if( p_stream->avc.i_pps > 0 )    {        bo_add_16be( avcC, p_stream->avc.i_pps );        bo_add_mem( avcC, p_stream->avc.i_pps, p_stream->avc.pps );    }    box_fix( avcC );    return avcC;}/* TODO: No idea about these values */static bo_t *GetSVQ3Tag( mp4_stream_t *p_stream ){    bo_t *smi = box_new( "SMI " );    if( p_stream->fmt.i_extra > 0x4e )    {        uint8_t *p_end = &((uint8_t*)p_stream->fmt.p_extra)[p_stream->fmt.i_extra];        uint8_t *p     = &((uint8_t*)p_stream->fmt.p_extra)[0x46];        while( p + 8 < p_end )        {            int i_size = GetDWBE( p );            if( i_size <= 1 )            {                /* FIXME handle 1 as long size */                break;            }            if( !strncmp( &p[4], "SMI ", 4 ) )            {                bo_add_mem( smi, p_end - p - 8, &p[8] );                return smi;            }            p += i_size;        }    }    /* Create a dummy one in fallback */    bo_add_fourcc( smi, "SEQH" );    bo_add_32be( smi, 0x5 );    bo_add_32be( smi, 0xe2c0211d );    bo_add_8( smi, 0xc0 );    box_fix( smi );    return smi;}static bo_t *GetUdtaTag( sout_mux_t *p_mux ){    sout_mux_sys_t *p_sys = p_mux->p_sys;    bo_t *udta = box_new( "udta" );    vlc_meta_t *p_meta = p_mux->p_sout->p_meta;    int i_track;    /* Requirements */    for( i_track = 0; i_track < p_sys->i_nb_streams; i_track++ )    {        mp4_stream_t *p_stream = p_sys->pp_streams[i_track];        if( p_stream->fmt.i_codec == VLC_FOURCC('m','p','4','v') ||            p_stream->fmt.i_codec == VLC_FOURCC('m','p','4','a') )        {            bo_t *box = box_new( "\251req" );            /* String length */            bo_add_16be( box, sizeof("QuickTime 6.0 or greater") - 1);            bo_add_16be( box, 0 );            bo_add_mem( box, sizeof("QuickTime 6.0 or greater") - 1,                        "QuickTime 6.0 or greater" );            box_fix( box );            box_gather( udta, box );            break;        }    }    /* Encoder */    {        bo_t *box = box_new( "\251enc" );        /* String length */        bo_add_16be( box, sizeof(PACKAGE_STRING " stream output") - 1);        bo_add_16be( box, 0 );        bo_add_mem( box, sizeof(PACKAGE_STRING " stream output") - 1,                    PACKAGE_STRING " stream output" );        box_fix( box );        box_gather( udta, box );    }    /* Misc atoms */    if( p_meta )    {        int i;        for( i = 0; i < p_meta->i_meta; i++ )        {            bo_t *box = NULL;            if( !strcmp( p_meta->name[i], VLC_META_TITLE ) )                box = box_new( "\251nam" );            else if( !strcmp( p_meta->name[i], VLC_META_AUTHOR ) )                box = box_new( "\251aut" );            else if( !strcmp( p_meta->name[i], VLC_META_ARTIST ) )                box = box_new( "\251ART" );            else if( !strcmp( p_meta->name[i], VLC_META_GENRE ) )                box = box_new( "\251gen" );            else if( !strcmp( p_meta->name[i], VLC_META_COPYRIGHT ) )                box = box_new( "\251cpy" );            else if( !strcmp( p_meta->name[i], VLC_META_DESCRIPTION ) )                box = box_new( "\251des" );            else if( !strcmp( p_meta->name[i], VLC_META_DATE ) )                box = box_new( "\251day" );            else if( !strcmp( p_meta->name[i], VLC_META_URL ) )                box = box_new( "\251url" );            if( box )            {                bo_add_16be( box, strlen( p_meta->value[i] ) );                bo_add_16be( box, 0 );                bo_add_mem( box, strlen( p_meta->value[i] ),                            p_meta->value[i] );                box_fix( box );                box_gather( udta, box );            }        }    }    box_fix( udta );    return udta;}static bo_t *GetSounBox( sout_mux_t *p_mux, mp4_stream_t *p_stream ){    sout_mux_sys_t *p_sys = p_mux->p_sys;    vlc_bool_t b_descr = VLC_FALSE;    bo_t *soun;    char fcc[4] = "    ";    int  i;    switch( p_stream->fmt.i_codec )    {    case VLC_FOURCC('m','p','4','a'):        memcpy( fcc, "mp4a", 4 );        b_descr = VLC_TRUE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -