Changeset 5c2cf083f90c34009b799ff65db74f27930a493d
- Timestamp:
- 23/01/04 18:56:14 (5 years ago)
- git-parent:
- Files:
-
- include/stream_output.h (modified) (3 diffs)
- modules/access_output/file.c (modified) (7 diffs)
- modules/access_output/udp.c (modified) (11 diffs)
- modules/mux/mp4.c (modified) (20 diffs)
- src/stream_output/stream_output.c (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
include/stream_output.h
rc89488f r5c2cf08 3 3 ***************************************************************************** 4 4 * Copyright (C) 2002 VideoLAN 5 * $Id: stream_output.h,v 1.1 8 2003/12/07 17:09:33gbazin Exp $5 * $Id: stream_output.h,v 1.19 2004/01/23 17:56:14 gbazin Exp $ 6 6 * 7 7 * Authors: Christophe Massiot <massiot@via.ecp.fr> … … 122 122 int (* pf_seek )( sout_access_out_t *, 123 123 off_t ); 124 int (* pf_read )( sout_access_out_t *, 125 sout_buffer_t * ); 124 126 int (* pf_write )( sout_access_out_t *, 125 127 sout_buffer_t * ); … … 296 298 VLC_EXPORT( void, sout_AccessOutDelete, ( sout_access_out_t * ) ); 297 299 VLC_EXPORT( int, sout_AccessOutSeek, ( sout_access_out_t *, off_t ) ); 300 VLC_EXPORT( int, sout_AccessOutRead, ( sout_access_out_t *, sout_buffer_t * ) ); 298 301 VLC_EXPORT( int, sout_AccessOutWrite, ( sout_access_out_t *, sout_buffer_t * ) ); 299 302 modules/access_output/file.c
r0d90e52 r5c2cf08 3 3 ***************************************************************************** 4 4 * Copyright (C) 2001, 2002 VideoLAN 5 * $Id: file.c,v 1.1 0 2003/12/04 12:33:43gbazin Exp $5 * $Id: file.c,v 1.11 2004/01/23 17:56:14 gbazin Exp $ 6 6 * 7 7 * Authors: Laurent Aimar <fenrir@via.ecp.fr> … … 62 62 static int Write( sout_access_out_t *, sout_buffer_t * ); 63 63 static int Seek ( sout_access_out_t *, off_t ); 64 static int Read ( sout_access_out_t *, sout_buffer_t * ); 64 65 65 66 /***************************************************************************** … … 98 99 return VLC_EGENERIC; 99 100 } 100 i_flags = O_ WRONLY|O_CREAT;101 i_flags = O_RDWR|O_CREAT; 101 102 if( sout_cfg_find_value( p_access->p_cfg, "append" ) ) 102 103 { … … 121 122 } 122 123 123 p_access->pf_write = Write; 124 p_access->pf_seek = Seek; 124 p_access->pf_write = Write; 125 p_access->pf_read = Read; 126 p_access->pf_seek = Seek; 125 127 126 128 msg_Info( p_access, "Open: name:`%s'", p_access->psz_name ); … … 133 135 static void Close( vlc_object_t * p_this ) 134 136 { 135 sout_access_out_t *p_access = (sout_access_out_t*)p_this;137 sout_access_out_t *p_access = (sout_access_out_t*)p_this; 136 138 137 139 if( strcmp( p_access->psz_name, "-" ) ) … … 149 151 /***************************************************************************** 150 152 * Read: standard read on a file descriptor. 153 *****************************************************************************/ 154 static int Read( sout_access_out_t *p_access, sout_buffer_t *p_buffer ) 155 { 156 if( strcmp( p_access->psz_name, "-" ) ) 157 { 158 return read( p_access->p_sys->i_handle, p_buffer->p_buffer, 159 p_buffer->i_size ); 160 } 161 else 162 { 163 msg_Err( p_access, "cannot seek while using stdout" ); 164 return VLC_EGENERIC; 165 } 166 } 167 168 /***************************************************************************** 169 * Write: standard write on a file descriptor. 151 170 *****************************************************************************/ 152 171 static int Write( sout_access_out_t *p_access, sout_buffer_t *p_buffer ) … … 174 193 static int Seek( sout_access_out_t *p_access, off_t i_pos ) 175 194 { 176 msg_Dbg( p_access, "Seek: pos:"I64Fd, (int64_t)i_pos );195 //msg_Dbg( p_access, "Seek: pos:"I64Fd, (int64_t)i_pos ); 177 196 178 197 if( strcmp( p_access->psz_name, "-" ) ) modules/access_output/udp.c
r8c510a9 r5c2cf08 3 3 ***************************************************************************** 4 4 * Copyright (C) 2001, 2002 VideoLAN 5 * $Id: udp.c,v 1.1 6 2003/11/17 14:46:37 massiotExp $5 * $Id: udp.c,v 1.17 2004/01/23 17:56:14 gbazin Exp $ 6 6 * 7 7 * Authors: Laurent Aimar <fenrir@via.ecp.fr> … … 54 54 55 55 #define DEFAULT_PORT 1234 56 #define LATENCY 10000057 #define MAX_ERROR 50000058 56 /***************************************************************************** 59 57 * Exported prototypes … … 131 129 network_socket_t socket_desc; 132 130 133 char *val; 131 vlc_value_t val; 132 char *psz_val; 134 133 135 134 if( !( p_sys = p_access->p_sys = … … 137 136 { 138 137 msg_Err( p_access, "Not enough memory" ); 139 return ( VLC_EGENERIC );138 return VLC_EGENERIC; 140 139 } 141 140 … … 185 184 { 186 185 msg_Err( p_access, "out of memory" ); 187 return ( VLC_EGENERIC );186 return VLC_EGENERIC; 188 187 } 189 188 … … 199 198 socket_desc.i_bind_port = 0; 200 199 socket_desc.i_ttl = 0; 201 if( ( val = sout_cfg_find_value( p_access->p_cfg, "ttl" ) ) )202 { 203 socket_desc.i_ttl = atoi( val );200 if( ( psz_val = sout_cfg_find_value( p_access->p_cfg, "ttl" ) ) ) 201 { 202 socket_desc.i_ttl = atoi( psz_val ); 204 203 } 205 204 p_sys->p_thread->p_private = (void*)&socket_desc; 206 if( !( p_network = module_Need( p_sys->p_thread, 207 "network", "" ) ) ) 205 if( !( p_network = module_Need( p_sys->p_thread, "network", "" ) ) ) 208 206 { 209 207 msg_Err( p_access, "failed to open a connection (udp)" ); 210 return ( VLC_EGENERIC );208 return VLC_EGENERIC; 211 209 } 212 210 module_Unneed( p_sys->p_thread, p_network ); 213 211 214 212 p_sys->p_thread->i_handle = socket_desc.i_handle; 215 p_sys->p_thread->i_caching = config_GetInt( p_this, "udp-sout-caching" ) * 1000; 216 if( ( val = sout_cfg_find_value( p_access->p_cfg, "caching" ) ) ) 217 { 218 p_sys->p_thread->i_caching = atoll( val ) * 1000; 219 } 220 221 p_sys->i_mtu = socket_desc.i_mtu; 213 214 var_Create( p_this, "udp-sout-caching", 215 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); 216 var_Get( p_this, "udp-sout-caching", &val ); 217 p_sys->p_thread->i_caching = val.i_int * 1000; 218 if( ( psz_val = sout_cfg_find_value( p_access->p_cfg, "caching" ) ) ) 219 { 220 p_sys->p_thread->i_caching = atoll( psz_val ) * 1000; 221 } 222 223 p_sys->i_mtu = socket_desc.i_mtu; 222 224 223 225 if( vlc_thread_create( p_sys->p_thread, "sout write thread", ThreadWrite, … … 226 228 msg_Err( p_access->p_sout, "cannot spawn sout access thread" ); 227 229 vlc_object_destroy( p_sys->p_thread ); 228 return ( VLC_EGENERIC );230 return VLC_EGENERIC; 229 231 } 230 232 … … 236 238 if( sout_cfg_find( p_access->p_cfg, "raw" ) ) 237 239 { 238 p_access->pf_write = WriteRaw;240 p_access->pf_write = WriteRaw; 239 241 } 240 242 else 241 243 { 242 p_access->pf_write = Write;243 } 244 p_access->pf_seek = Seek; 245 246 msg_Info( p_access, "Open: addr:`%s' port:`%d'", 247 psz_dst_addr, i_dst_port);244 p_access->pf_write = Write; 245 } 246 247 p_access->pf_seek = Seek; 248 249 msg_Info( p_access, "Open: addr:`%s' port:`%d'", psz_dst_addr, i_dst_port); 248 250 249 251 free( psz_dst_addr ); … … 256 258 static void Close( vlc_object_t * p_this ) 257 259 { 258 sout_access_out_t *p_access = (sout_access_out_t*)p_this;259 sout_access_out_sys_t *p_sys = p_access->p_sys;260 int i;260 sout_access_out_t *p_access = (sout_access_out_t*)p_this; 261 sout_access_out_sys_t *p_sys = p_access->p_sys; 262 int i; 261 263 262 264 p_sys->p_thread->b_die = 1; 263 265 for( i = 0; i < 10; i++ ) 264 266 { 265 sout_buffer_t *p_dummy;267 sout_buffer_t *p_dummy; 266 268 267 269 p_dummy = sout_BufferNew( p_access->p_sout, p_sys->i_mtu ); … … 297 299 static int Write( sout_access_out_t *p_access, sout_buffer_t *p_buffer ) 298 300 { 299 sout_access_out_sys_t *p_sys = p_access->p_sys;301 sout_access_out_sys_t *p_sys = p_access->p_sys; 300 302 unsigned int i_write; 301 303 … … 357 359 static int Seek( sout_access_out_t *p_access, off_t i_pos ) 358 360 { 359 360 361 msg_Err( p_access, "udp sout access cannot seek" ); 361 362 return( -1 ); modules/mux/mp4.c
rd4dda46 r5c2cf08 3 3 ***************************************************************************** 4 4 * Copyright (C) 2001, 2002, 2003 VideoLAN 5 * $Id: mp4.c,v 1. 9 2004/01/13 15:54:09gbazin Exp $5 * $Id: mp4.c,v 1.10 2004/01/23 17:56:14 gbazin Exp $ 6 6 * 7 7 * Authors: Laurent Aimar <fenrir@via.ecp.fr> … … 43 43 * Exported prototypes 44 44 *****************************************************************************/ 45 static int Open ( vlc_object_t * );46 static void Close ( vlc_object_t * );45 static int Open ( vlc_object_t * ); 46 static void Close ( vlc_object_t * ); 47 47 48 48 static int Capability(sout_mux_t *, int, void *, void * ); … … 54 54 * Module descriptor 55 55 *****************************************************************************/ 56 #define FASTSTART_TEXT N_("Create \"Fast start\" files") 57 #define FASTSTART_LONGTEXT N_( \ 58 "When this option is turned on, \"Fast start\" files will be created. " \ 59 "(\"Fast start\" files are optimized for download, allowing the user " \ 60 "to start previewing the file while it is downloading).") 61 56 62 vlc_module_begin(); 57 63 set_description( _("MP4/MOV muxer") ); 64 65 add_category_hint( "MP4/MOV muxer", NULL, VLC_TRUE ); 66 add_bool( "mp4-faststart", 1, NULL, FASTSTART_TEXT, FASTSTART_LONGTEXT, VLC_TRUE ); 67 58 68 set_capability( "sout mux", 5 ); 59 69 add_shortcut( "mp4" ); … … 62 72 vlc_module_end(); 63 73 74 /***************************************************************************** 75 * Local prototypes 76 *****************************************************************************/ 64 77 typedef struct 65 78 { … … 85 98 /* stats */ 86 99 mtime_t i_duration; 100 101 /* for later stco fix-up (fast start files) */ 102 uint64_t i_stco_pos; 103 vlc_bool_t b_stco64; 104 87 105 } mp4_stream_t; 88 106 … … 91 109 vlc_bool_t b_mov; 92 110 vlc_bool_t b_64_ext; 111 vlc_bool_t b_fast_start; 93 112 94 113 uint64_t i_mdat_pos; … … 101 120 }; 102 121 103 104 typedef struct bo_t bo_t; 105 struct bo_t 122 typedef struct bo_t 106 123 { 107 124 vlc_bool_t b_grow; … … 111 128 uint8_t *p_buffer; 112 129 113 } ;130 } bo_t; 114 131 115 132 static void bo_init ( bo_t *, int , uint8_t *, vlc_bool_t ); … … 122 139 static void bo_add_bo ( bo_t *, bo_t * ); 123 140 static void bo_add_mem ( bo_t *, int , uint8_t * ); 124 static void bo_add_descr ( bo_t *, uint8_t , uint32_t );141 static void bo_add_descr( bo_t *, uint8_t , uint32_t ); 125 142 126 143 static void bo_fix_32be ( bo_t *, int , uint32_t ); … … 136 153 static int64_t get_timestamp(); 137 154 138 static sout_buffer_t * bo_to_sout( sout_instance_t *p_sout, bo_t *box );155 static sout_buffer_t *bo_to_sout( sout_instance_t *p_sout, bo_t *box ); 139 156 140 157 /***************************************************************************** … … 155 172 p_sys->i_start_dts = 0; 156 173 157 msg_ Info( p_mux, "Open" );174 msg_Dbg( p_mux, "Open" ); 158 175 159 176 p_mux->pf_capacity = Capability; … … 334 351 } 335 352 336 /***************************************************************************** 337 * Close: 338 *****************************************************************************/ 353 static bo_t *GetUdtaTag( sout_mux_t *p_mux ) 354 { 355 sout_mux_sys_t *p_sys = p_mux->p_sys; 356 bo_t *udta = box_new( "udta" ); 357 int i_track; 358 359 /* Requirements */ 360 for( i_track = 0; i_track < p_sys->i_nb_streams; i_track++ ) 361 { 362 mp4_stream_t *p_stream = p_sys->pp_streams[i_track]; 363 364 if( p_stream->p_fmt->i_codec == VLC_FOURCC('m','p','4','v') || 365 p_stream->p_fmt->i_codec == VLC_FOURCC('m','p','4','a') ) 366 { 367 bo_t *box = box_new( "\251req" ); 368 /* String length */ 369 bo_add_16be( box, sizeof("QuickTime 6.0 or greater") - 1); 370 bo_add_16be( box, 0 ); 371 bo_add_mem( box, sizeof("QuickTime 6.0 or greater") - 1, 372 "QuickTime 6.0 or greater" ); 373 box_fix( box ); 374 box_gather( udta, box ); 375 break; 376 } 377 } 378 379 /* Encoder */ 380 { 381 bo_t *box = box_new( "\251enc" ); 382 /* String length */ 383 bo_add_16be( box, sizeof(PACKAGE_STRING " stream output") - 1); 384 bo_add_16be( box, 0 ); 385 bo_add_mem( box, sizeof(PACKAGE_STRING " stream output") - 1, 386 PACKAGE_STRING " stream output" ); 387 box_fix( box ); 388 box_gather( udta, box ); 389 } 390 391 box_fix( udta ); 392 return udta; 393 } 394 339 395 static uint32_t mvhd_matrix[9] = 340 396 { 0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000 }; 341 397 342 static void Close( vlc_object_t * p_this ) 343 { 344 sout_mux_t *p_mux = (sout_mux_t*)p_this; 345 sout_mux_sys_t *p_sys = p_mux->p_sys; 346 sout_buffer_t *p_hdr; 347 bo_t bo; 398 static bo_t *GetMoovTag( sout_mux_t *p_mux ) 399 { 400 sout_mux_sys_t *p_sys = p_mux->p_sys; 401 348 402 bo_t *moov, *mvhd; 349 403 unsigned int i; … … 352 406 uint32_t i_movie_timescale = 90000; 353 407 int64_t i_movie_duration = 0; 354 msg_Info( p_mux, "Close" );355 356 /* create general info */357 for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )358 {359 mp4_stream_t *p_stream;360 361 p_stream = p_sys->pp_streams[i_trak];362 363 i_movie_duration = __MAX( i_movie_duration, p_stream->i_duration );364 }365 msg_Dbg( p_mux, "movie duration %ds",366 (uint32_t)( i_movie_duration / (mtime_t)1000000 ) );367 368 i_movie_duration = i_movie_duration *369 (int64_t)i_movie_timescale / (int64_t)1000000;370 371 /* *** update mdat size *** */372 bo_init ( &bo, 0, NULL, VLC_TRUE );373 if( p_sys->i_pos - p_sys->i_mdat_pos >= (((uint64_t)1)<<32) )374 {375 /* Extended size */376 bo_add_32be ( &bo, 1 );377 bo_add_fourcc( &bo, "mdat" );378 bo_add_64be ( &bo, p_sys->i_pos - p_sys->i_mdat_pos );379 }380 else381 {382 bo_add_32be ( &bo, 8 );383 bo_add_fourcc( &bo, "wide" );384 bo_add_32be ( &bo, p_sys->i_pos - p_sys->i_mdat_pos - 8 );385 bo_add_fourcc( &bo, "mdat" );386 }387 388 p_hdr = bo_to_sout( p_mux->p_sout, &bo );389 free( bo.p_buffer );390 391 /* seek to mdat */392 sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos );393 sout_AccessOutWrite( p_mux->p_access, p_hdr );394 395 /* Now create header */396 sout_AccessOutSeek( p_mux->p_access, p_sys->i_pos );397 408 398 409 moov = box_new( "moov" ); … … 455 466 uint32_t i_timescale; 456 467 uint32_t i_chunk_count; 468 unsigned int i_chunk; 457 469 458 470 bo_t *trak; … … 467 479 bo_t *stsd; 468 480 bo_t *stts; 481 bo_t *stco; 482 bo_t *stsc; 469 483 bo_t *stsz; 470 484 … … 702 716 bo_add_32be( soun, 0 ); // vendor 703 717 bo_add_16be( soun, p_stream->p_fmt->audio.i_channels ); // channel-count 704 bo_add_16be( soun, 16); // FIXME sample size 718 // sample size 719 bo_add_16be( soun, p_stream->p_fmt->audio.i_bitspersample ? 720 p_stream->p_fmt->audio.i_bitspersample : 16 ); 705 721 bo_add_16be( soun, -2 ); // compression id 706 722 bo_add_16be( soun, 0 ); // packet size (0) … … 832 848 box_gather( stbl, stsd ); 833 849 834 /* we will create chunk table and stsc table FIXME optim stsc table FIXME */ 850 /* we will create chunk table and stsc table 851 * FIXME optim stsc table FIXME */ 835 852 i_chunk_count = 0; 836 853 for( i = 0; i < p_stream->i_entry_count; ) … … 852 869 853 870 /* chunk offset table */ 871 p_stream->i_stco_pos = stbl->i_buffer + 16; 854 872 if( p_sys->i_pos >= (((uint64_t)0x1) << 32) ) 855 873 { 856 874 /* 64 bits version */ 857 bo_t *co64;858 bo_t *stsc;859 860 unsigned int i_chunk;861 862 875 msg_Dbg( p_mux, "creating %d chunk (co64)", i_chunk_count ); 863 864 co64 = box_full_new( "co64", 0, 0 ); 865 bo_add_32be( co64, i_chunk_count ); 866 867 stsc = box_full_new( "stsc", 0, 0 ); 868 bo_add_32be( stsc, i_chunk_count ); // entry-count 876 p_stream->b_stco64 = VLC_TRUE; 877 stco = box_full_new( "co64", 0, 0 ); 878 } 879 else 880 { 881 /* 32 bits version */ 882 msg_Dbg( p_mux, "creating %d chunk (stco)", i_chunk_count ); 883 p_stream->b_stco64 = VLC_FALSE; 884 stco = box_full_new( "stco", 0, 0 ); 885 } 886 887 bo_add_32be( stco, i_chunk_count ); 888 889 stsc = box_full_new( "stsc", 0, 0 ); 890 bo_add_32be( stsc, i_chunk_count ); // entry-count 891 for( i_chunk = 0, i = 0; i < p_stream->i_entry_count; i_chunk++ ) 892 { 893 int i_first; 894 895 if( p_stream->b_stco64 ) 896 bo_add_64be( stco, p_stream->entry[i].i_pos ); 897 else 898 bo_add_32be( stco, p_stream->entry[i].i_pos ); 899 900 i_first = i; 901 902 while( i < p_stream->i_entry_count ) 903 { 904 if( i + 1 < p_stream->i_entry_count && 905 p_stream->entry[i].i_pos + p_stream->entry[i].i_size 906 != p_stream->entry[i + 1].i_pos ) 907 { 908 i++; 909 break; 910 } 911 912 i++; 913 } 914 bo_add_32be( stsc, 1 + i_chunk ); // first-chunk 915 bo_add_32be( stsc, i - i_first ) ; // samples-per-chunk 916 bo_add_32be( stsc, 1 ); // sample-descr-index 917 } 918 919 /* append stco to stbl */ 920 box_fix( stco ); 921 box_gather( stbl, stco ); 922 923 /* append stsc to stbl */ 924 box_fix( stsc ); 925 box_gather( stbl, stsc ); 926 927 /* add stts */ 928 stts = box_full_new( "stts", 0, 0 ); 929 bo_add_32be( stts, 0 ); // fixed latter 930 for( i = 0, i_index = 0; i < p_stream->i_entry_count; i_index++) 931 { 932 int64_t i_delta; 933 int i_first; 934 935 i_first = i; 936 i_delta = p_stream->entry[i].i_length; 937 938 while( i < p_stream->i_entry_count ) 939 { 940 if( i + 1 < p_stream->i_entry_count && 941 p_stream->entry[i + 1].i_length != i_delta ) 942 { 943 i++; 944 break; 945 } 946 947 i++; 948 } 949 950 bo_add_32be( stts, i - i_first ); // sample-count 951 bo_add_32be( stts, i_delta * (int64_t)i_timescale / 952 (int64_t)1000000 ); // sample-delta 953 } 954 bo_fix_32be( stts, 12, i_index ); 955 956 /* append stts to stbl */ 957 box_fix( stts ); 958 box_gather( stbl, stts ); 959 960 /* FIXME add ctts ?? FIXME */ 961 962 stsz = box_full_new( "stsz", 0, 0 ); 963 bo_add_32be( stsz, 0 ); // sample-size 964 bo_add_32be( stsz, p_stream->i_entry_count ); // sample-count 965 for( i = 0; i < p_stream->i_entry_count; i++ ) 966 { 967 bo_add_32be( stsz, p_stream->entry[i].i_size ); // sample-size 968 } 969 /* append stsz to stbl */ 970 box_fix( stsz ); 971 box_gather( stbl, stsz ); 972 973 /* append stbl to minf */ 974 box_fix( stbl ); 975 p_stream->i_stco_pos += minf->i_buffer; 976 box_gather( minf, stbl ); 977 978 /* append minf to mdia */ 979 box_fix( minf ); 980 p_stream->i_stco_pos += mdia->i_buffer; 981 box_gather( mdia, minf ); 982 983 /* append mdia to trak */ 984 box_fix( mdia ); 985 p_stream->i_stco_pos += trak->i_buffer; 986 box_gather( trak, mdia ); 987 988 /* append trak to moov */ 989 box_fix( trak ); 990 p_stream->i_stco_pos += moov->i_buffer; 991 box_gather( moov, trak ); 992 } 993 994 /* Add user data tags */ 995 box_gather( moov, GetUdtaTag( p_mux ) ); 996 997 box_fix( moov ); 998 return moov; 999 } 1000 1001 /***************************************************************************** 1002 * Close: 1003 *****************************************************************************/ 1004 static void Close( vlc_object_t * p_this ) 1005 { 1006 sout_mux_t *p_mux = (sout_mux_t*)p_this; 1007 sout_mux_sys_t *p_sys = p_mux->p_sys; 1008 sout_buffer_t *p_hdr; 1009 bo_t bo, *moov; 1010 vlc_value_t val; 1011 1012 int i_trak; 1013 uint64_t i_moov_pos; 1014 1015 uint32_t i_movie_timescale = 90000; 1016 int64_t i_movie_duration = 0; 1017 1018 msg_Dbg( p_mux, "Close" ); 1019 1020 /* Create general info */ 1021 for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ ) 1022 { 1023 mp4_stream_t *p_stream = p_sys->pp_streams[i_trak]; 1024 i_movie_duration = __MAX( i_movie_duration, p_stream->i_duration ); 1025 } 1026 msg_Dbg( p_mux, "movie duration %ds", 1027 (uint32_t)( i_movie_duration / (mtime_t)1000000 ) ); 1028 1029 i_movie_duration = i_movie_duration * i_movie_timescale / 1000000; 1030 1031 /* Update mdat size */ 1032 bo_init( &bo, 0, NULL, VLC_TRUE ); 1033 if( p_sys->i_pos - p_sys->i_mdat_pos >= (((uint64_t)1)<<32) ) 1034 { 1035 /* Extended size */ 1036 bo_add_32be ( &bo, 1 ); 1037 bo_add_fourcc( &bo, "mdat" ); 1038 bo_add_64be ( &bo, p_sys->i_pos - p_sys->i_mdat_pos ); 1039 } 1040 else 1041 { 1042 bo_add_32be ( &bo, 8 ); 1043 bo_add_fourcc( &bo, "wide" ); 1044 bo_add_32be ( &bo, p_sys->i_pos - p_sys->i_mdat_pos - 8 ); 1045 bo_add_fourcc( &bo, "mdat" ); 1046 } 1047 p_hdr = bo_to_sout( p_mux->p_sout, &bo ); 1048 free( bo.p_buffer ); 1049 1050 sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos ); 1051 sout_AccessOutWrite( p_mux->p_access, p_hdr ); 1052 1053 /* Create MOOV header */ 1054 i_moov_pos = p_sys->i_pos; 1055 moov = GetMoovTag( p_mux ); 1056 1057 /* Check we need to create "fast start" files */ 1058 var_Create( p_this, "mp4-faststart", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); 1059 var_Get( p_this, "mp4-faststart", &val ); 1060 p_sys->b_fast_start = val.b_bool; 1061 while( p_sys->b_fast_start ) 1062 { 1063 /* Move data to the end of the file so we can fit the moov header 1064 * at the start */ 1065 sout_buffer_t *p_buf; 1066 int64_t i_chunk, i_size = p_sys->i_pos - p_sys->i_mdat_pos; 1067 int i_moov_size = moov->i_buffer; 1068 1069 while( i_size > 0 ) 1070 { 1071 i_chunk = __MIN( 32768, i_size ); 1072 p_buf = sout_BufferNew( p_mux->p_sout, i_chunk ); 1073 sout_AccessOutSeek( p_mux->p_access, 1074 p_sys->i_mdat_pos + i_size - i_chunk ); 1075 if( sout_AccessOutRead( p_mux->p_access, p_buf ) < i_chunk ) 1076 { 1077 msg_Warn( p_this, "read() not supported by acces output, " 1078 "won't create a fast start file" ); 1079 p_sys->b_fast_start = VLC_FALSE; 1080 break; 1081 } 1082 sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos + i_size + 1083 i_moov_size - i_chunk ); 1084 sout_AccessOutWrite( p_mux->p_access, p_buf ); 1085 i_size -= i_chunk; 1086 } 1087 1088 if( !p_sys->b_fast_start ) break; 1089 1090 /* Fix-up samples to chunks table in MOOV header */ 1091 for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ ) 1092 { 1093 mp4_stream_t *p_stream = p_sys->pp_streams[i_trak]; 1094 unsigned int i; 1095 int i_chunk; 1096 1097 moov->i_buffer = p_stream->i_stco_pos; 869 1098 for( i_chunk = 0, i = 0; i < p_stream->i_entry_count; i_chunk++ ) 870 1099 { 871 i nt i_first;872 bo_add_64be( co64, p_stream->entry[i].i_pos);873 874 i_first = i;1100 if( p_stream->b_stco64 ) 1101 bo_add_64be( moov, p_stream->entry[i].i_pos + i_moov_size); 1102 else 1103 bo_add_32be( moov, p_stream->entry[i].i_pos + i_moov_size); 875 1104 876 1105 while( i < p_stream->i_entry_count ) … … 886 1115 i++; 887 1116 } 888 bo_add_32be( stsc, 1 + i_chunk ); // first-chunk 889 bo_add_32be( stsc, i - i_first ) ; // samples-per-chunk 890 bo_add_32be( stsc, 1 ); // sample-descr-index 891 } 892 /* append co64 to stbl */ 893 box_fix( co64 ); 894 box_gather( stbl, co64 ); 895 896 /* append stsc to stbl */ 897 box_fix( stsc ); 898 box_gather( stbl, stsc ); 899 } 900 else 901 { 902 /* 32 bits version */ 903 bo_t *stco; 904 bo_t *stsc; 905 906 unsigned int i_chunk; 907 908 msg_Dbg( p_mux, "creating %d chunk (stco)", i_chunk_count ); 909 910 stco = box_full_new( "stco", 0, 0 ); 911 bo_add_32be( stco, i_chunk_count ); 912 913 stsc = box_full_new( "stsc", 0, 0 ); 914 bo_add_32be( stsc, i_chunk_count ); // entry-count 915 for( i_chunk = 0, i = 0; i < p_stream->i_entry_count; i_chunk++ ) 916 { 917 int i_first; 918 bo_add_32be( stco, p_stream->entry[i].i_pos ); 919 920 i_first = i; 921 922 while( i < p_stream->i_entry_count ) 923 { 924 if( i + 1 < p_stream->i_entry_count && 925 p_stream->entry[i].i_pos + p_stream->entry[i].i_size 926 != p_stream->entry[i + 1].i_pos ) 927 { 928 i++; 929 break; 930 } 931 932 i++; 933 } 934 bo_add_32be( stsc, 1 + i_chunk ); // first-chunk 935 bo_add_32be( stsc, i - i_first ) ; // samples-per-chunk 936 bo_add_32be( stsc, 1 ); // sample-descr-index 937 } 938 /* append stco to stbl */ 939 box_fix( stco ); 940 box_gather( stbl, stco ); 941 942 /* append stsc to stbl */ 943 box_fix( stsc ); 944 box_gather( stbl, stsc ); 945 } 946 947 948 /* add stts */ 949 stts = box_full_new( "stts", 0, 0 ); 950 bo_add_32be( stts, 0 ); // fixed latter 951 for( i = 0, i_index = 0; i < p_stream->i_entry_count; i_index++) 952 { 953 int64_t i_delta; 954 int i_first; 955 956 i_first = i; 957 i_delta = p_stream->entry[i].i_length; 958 959 while( i < p_stream->i_entry_count ) 960 { 961 if( i + 1 < p_stream->i_entry_count && 962 p_stream->entry[i + 1].i_length != i_delta ) 963 { 964 i++; 965 break; 966 } 967 968 i++; 969 } 970 971 bo_add_32be( stts, i - i_first ); // sample-count 972 bo_add_32be( stts, i_delta * (int64_t)i_timescale / 973 (int64_t)1000000 ); // sample-delta 974 } 975 bo_fix_32be( stts, 12, i_index ); 976 977 /* append stts to stbl */ 978 box_fix( stts ); 979 box_gather( stbl, stts ); 980 981 /* FIXME add ctts ?? FIXME */ 982 983 stsz = box_full_new( "stsz", 0, 0 ); 984 bo_add_32be( stsz, 0 ); // sample-size 985 bo_add_32be( stsz, p_stream->i_entry_count ); // sample-count 986 for( i = 0; i < p_stream->i_entry_count; i++ ) 987 { 988 bo_add_32be( stsz, p_stream->entry[i].i_size ); // sample-size 989 } 990 /* append stsz to stbl */ 991 box_fix( stsz ); 992 box_gather( stbl, stsz ); 993 994 /* append stbl to minf */ 995 box_fix( stbl ); 996 box_gather( minf, stbl ); 997 998 /* append minf to mdia */ 999 box_fix( minf ); 1000 box_gather( mdia, minf ); 1001 1002 /* append mdia to trak */ 1003 box_fix( mdia ); 1004 box_gather( trak, mdia ); 1005 1006 /* append trak to moov */ 1007 box_fix( trak ); 1008 box_gather( moov, trak ); 1009 } 1010 1011 box_fix( moov ); 1117 } 1118 } 1119 1120 moov->i_buffer = i_moov_size; 1121 i_moov_pos = p_sys->i_mdat_pos; 1122 p_sys->b_fast_start = VLC_FALSE; 1123 } 1124 1125 /* Write MOOV header */ 1126 sout_AccessOutSeek( p_mux->p_access, i_moov_pos ); 1012 1127 box_send( p_mux, moov ); 1013 1128 1014 /* *** release memory ****/1129 /* Clean-up */ 1015 1130 for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ ) 1016 1131 { 1017 mp4_stream_t *p_stream; 1018 1019 p_stream = p_sys->pp_streams[i_trak]; 1132 mp4_stream_t *p_stream = p_sys->pp_streams[i_trak]; 1020 1133 1021 1134 if( p_stream->p_fmt->p_extra ) … … 1397 1510 } 1398 1511 1399 1400 1512 static sout_buffer_t * bo_to_sout( sout_instance_t *p_sout, bo_t *box ) 1401 1513 { src/stream_output/stream_output.c
r25cd132 r5c2cf08 3 3 ***************************************************************************** 4 4 * Copyright (C) 2002-2004 VideoLAN 5 * $Id: stream_output.c,v 1.3 7 2004/01/06 12:02:06 zorglubExp $5 * $Id: stream_output.c,v 1.38 2004/01/23 17:56:14 gbazin Exp $ 6 6 * 7 7 * Authors: Christophe Massiot <massiot@via.ecp.fr> … … 239 239 240 240 241 int sout_InputSendBuffer( sout_packetizer_input_t *p_input, sout_buffer_t *p_buffer ) 241 int sout_InputSendBuffer( sout_packetizer_input_t *p_input, 242 sout_buffer_t *p_buffer ) 242 243 { 243 244 sout_instance_t *p_sout = p_input->p_sout; … … 273 274 } 274 275 275 psz_next = sout_cfg_parser( &p_access->psz_access, &p_access->p_cfg, psz_access ); 276 psz_next = sout_cfg_parser( &p_access->psz_access, &p_access->p_cfg, 277 psz_access ); 276 278 if( psz_next ) 277 279 { … … 282 284 p_access->p_sys = NULL; 283 285 p_access->pf_seek = NULL; 286 p_access->pf_read = NULL; 284 287 p_access->pf_write = NULL; 285 288 … … 318 321 * sout_AccessSeek: 319 322 *****************************************************************************/ 320 int sout_AccessOutSeek( sout_access_out_t *p_access, off_t i_pos ) 321 { 322 return( p_access->pf_seek( p_access, i_pos ) ); 323 int sout_AccessOutSeek( sout_access_out_t *p_access, off_t i_pos ) 324 { 325 return p_access->pf_seek( p_access, i_pos ); 326 } 327 328 /***************************************************************************** 329 * sout_AccessRead: 330 *****************************************************************************/ 331 int sout_AccessOutRead( sout_access_out_t *p_access, sout_buffer_t *p_buffer ) 332 { 333 return ( p_access->pf_read ? 334 p_access->pf_read( p_access, p_buffer ) : VLC_EGENERIC ); 323 335 } 324 336 … … 326 338 * sout_AccessWrite: 327 339 *****************************************************************************/ 328 int sout_AccessOutWrite( sout_access_out_t *p_access, sout_buffer_t *p_buffer ) 329 { 330 return( p_access->pf_write( p_access, p_buffer ) ); 331 } 332 340 int sout_AccessOutWrite( sout_access_out_t *p_access, sout_buffer_t *p_buffer ) 341 { 342 return p_access->pf_write( p_access, p_buffer ); 343 } 333 344 334 345 /*****************************************************************************
