| 164 | | if( !p_dec->fmt_out.i_extra ) |
|---|
| 165 | | { |
|---|
| 166 | | m4v_FindVol( p_dec, p_block ); |
|---|
| 167 | | } |
|---|
| 168 | | |
|---|
| 169 | | /* Drop blocks until we have a VOL */ |
|---|
| 170 | | if( !p_dec->fmt_out.i_extra ) |
|---|
| 171 | | { |
|---|
| 172 | | block_Release( p_block ); |
|---|
| 173 | | return NULL; |
|---|
| 174 | | } |
|---|
| 175 | | |
|---|
| 176 | | /* TODO: Date management */ |
|---|
| 177 | | p_block->i_length = 1000000 / 25; |
|---|
| 178 | | |
|---|
| 179 | | *pp_block = NULL; |
|---|
| 180 | | return p_block; |
|---|
| | 189 | /* Append data */ |
|---|
| | 190 | if( p_sys->i_buffer + p_block->i_buffer > p_sys->i_buffer_size ) |
|---|
| | 191 | { |
|---|
| | 192 | p_sys->i_buffer_size += p_block->i_buffer + 1024; |
|---|
| | 193 | p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size ); |
|---|
| | 194 | } |
|---|
| | 195 | memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer, |
|---|
| | 196 | p_block->i_buffer ); |
|---|
| | 197 | p_sys->i_buffer += p_block->i_buffer; |
|---|
| | 198 | |
|---|
| | 199 | if( p_sys->i_buffer > 10*1000000 ) |
|---|
| | 200 | { |
|---|
| | 201 | msg_Err( p_dec, "mmh reseting context" ); |
|---|
| | 202 | p_sys->i_buffer = 0; |
|---|
| | 203 | } |
|---|
| | 204 | |
|---|
| | 205 | /* Search vop */ |
|---|
| | 206 | p_start = &p_sys->p_buffer[p_sys->i_buffer - p_block->i_buffer - 4]; |
|---|
| | 207 | if( p_start < p_sys->p_buffer ) |
|---|
| | 208 | { |
|---|
| | 209 | p_start = p_sys->p_buffer; |
|---|
| | 210 | } |
|---|
| | 211 | for( ;; ) |
|---|
| | 212 | { |
|---|
| | 213 | if( m4v_FindStartCode( &p_start, &p_sys->p_buffer[p_sys->i_buffer] ) ) |
|---|
| | 214 | { |
|---|
| | 215 | block_Release( p_block ); |
|---|
| | 216 | *pp_block = NULL; |
|---|
| | 217 | return p_chain_out; |
|---|
| | 218 | } |
|---|
| | 219 | /* fprintf( stderr, "start code=0x1%2.2x\n", p_start[3] ); */ |
|---|
| | 220 | |
|---|
| | 221 | if( p_vol ) |
|---|
| | 222 | { |
|---|
| | 223 | /* Copy the complete VOL */ |
|---|
| | 224 | p_dec->fmt_out.i_extra = p_start - p_vol; |
|---|
| | 225 | p_dec->fmt_out.p_extra = malloc( p_dec->fmt_out.i_extra ); |
|---|
| | 226 | memcpy( p_dec->fmt_out.p_extra, p_vol, p_dec->fmt_out.i_extra ); |
|---|
| | 227 | m4v_VOLParse( &p_dec->fmt_out, |
|---|
| | 228 | p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); |
|---|
| | 229 | |
|---|
| | 230 | p_vol = NULL; |
|---|
| | 231 | } |
|---|
| | 232 | if( p_sys->b_vop ) |
|---|
| | 233 | { |
|---|
| | 234 | /* Output the complete VOP we have */ |
|---|
| | 235 | int i_out = p_start - p_sys->p_buffer; |
|---|
| | 236 | block_t *p_out = block_New( p_dec, i_out ); |
|---|
| | 237 | |
|---|
| | 238 | /* extract data */ |
|---|
| | 239 | memcpy( p_out->p_buffer, p_sys->p_buffer, i_out ); |
|---|
| | 240 | if( i_out < p_sys->i_buffer ) |
|---|
| | 241 | { |
|---|
| | 242 | memmove( p_sys->p_buffer, &p_sys->p_buffer[i_out], |
|---|
| | 243 | p_sys->i_buffer - i_out ); |
|---|
| | 244 | } |
|---|
| | 245 | p_sys->i_buffer -= i_out; |
|---|
| | 246 | p_start -= i_out; |
|---|
| | 247 | |
|---|
| | 248 | /* FIXME do proper dts/pts */ |
|---|
| | 249 | p_out->i_pts = p_sys->i_pts; |
|---|
| | 250 | p_out->i_dts = p_sys->i_dts; |
|---|
| | 251 | /* FIXME doesn't work when there is multiple VOP in one block */ |
|---|
| | 252 | if( p_block->i_dts > p_sys->i_dts ) |
|---|
| | 253 | { |
|---|
| | 254 | p_out->i_length = p_block->i_dts - p_sys->i_dts; |
|---|
| | 255 | } |
|---|
| | 256 | |
|---|
| | 257 | if( p_dec->fmt_out.i_extra > 0 ) |
|---|
| | 258 | { |
|---|
| | 259 | block_ChainAppend( &p_chain_out, p_out ); |
|---|
| | 260 | } |
|---|
| | 261 | else |
|---|
| | 262 | { |
|---|
| | 263 | msg_Warn( p_dec, "waiting for VOL" ); |
|---|
| | 264 | block_Release( p_out ); |
|---|
| | 265 | } |
|---|
| | 266 | |
|---|
| | 267 | #if 0 |
|---|
| | 268 | fprintf( stderr, "pts=%lld dts=%lld length=%lldms\n", |
|---|
| | 269 | p_out->i_pts, p_out->i_dts, |
|---|
| | 270 | p_out->i_length / 1000 ); |
|---|
| | 271 | #endif |
|---|
| | 272 | p_sys->b_vop = VLC_FALSE; |
|---|
| | 273 | } |
|---|
| | 274 | |
|---|
| | 275 | if( p_start[3] >= 0x20 && p_start[3] <= 0x2f ) |
|---|
| | 276 | { |
|---|
| | 277 | /* Start of the VOL */ |
|---|
| | 278 | p_vol = p_start; |
|---|
| | 279 | } |
|---|
| | 280 | else if( p_start[3] == 0xb6 ) |
|---|
| | 281 | { |
|---|
| | 282 | p_sys->b_vop = VLC_TRUE; |
|---|
| | 283 | p_sys->i_pts = p_block->i_pts; |
|---|
| | 284 | p_sys->i_dts = p_block->i_dts; |
|---|
| | 285 | } |
|---|
| | 286 | p_start += 4; /* Next */ |
|---|
| | 287 | } |
|---|
| 186 | | static int m4v_FindStartCode( uint8_t **pp_data, uint8_t *p_end ) |
|---|
| 187 | | { |
|---|
| 188 | | for( ; *pp_data < p_end - 4; (*pp_data)++ ) |
|---|
| 189 | | { |
|---|
| 190 | | if( (*pp_data)[0] == 0 && (*pp_data)[1] == 0 && (*pp_data)[2] == 1 ) |
|---|
| 191 | | { |
|---|
| 192 | | return 0; |
|---|
| 193 | | } |
|---|
| 194 | | } |
|---|
| 195 | | return -1; |
|---|
| 196 | | } |
|---|
| 197 | | |
|---|
| 198 | | static int m4v_FindVol( decoder_t *p_dec, block_t *p_block ) |
|---|
| 199 | | { |
|---|
| 200 | | uint8_t *p_vol_begin, *p_vol_end, *p_end; |
|---|
| 201 | | |
|---|
| 202 | | /* search if p_block contains with a vol */ |
|---|
| 203 | | p_vol_begin = p_block->p_buffer; |
|---|
| 204 | | p_vol_end = NULL; |
|---|
| 205 | | p_end = p_block->p_buffer + p_block->i_buffer; |
|---|
| | 293 | static int m4v_FindStartCode( uint8_t **pp_start, uint8_t *p_end ) |
|---|
| | 294 | { |
|---|
| | 295 | uint8_t *p = *pp_start; |
|---|
| | 296 | |
|---|
| | 297 | for( p = *pp_start; p < p_end - 4; p++ ) |
|---|
| | 298 | { |
|---|
| | 299 | if( p[0] == 0 && p[1] == 0 && p[2] == 1 ) |
|---|
| | 300 | { |
|---|
| | 301 | *pp_start = p; |
|---|
| | 302 | return VLC_SUCCESS; |
|---|
| | 303 | } |
|---|
| | 304 | } |
|---|
| | 305 | |
|---|
| | 306 | *pp_start = p_end; |
|---|
| | 307 | return VLC_EGENERIC; |
|---|
| | 308 | } |
|---|
| | 309 | |
|---|
| | 310 | |
|---|
| | 311 | /* look at ffmpeg av_log2 ;) */ |
|---|
| | 312 | static int vlc_log2( unsigned int v ) |
|---|
| | 313 | { |
|---|
| | 314 | int n = 0; |
|---|
| | 315 | static const int vlc_log2_table[16] = |
|---|
| | 316 | { |
|---|
| | 317 | 0,0,1,1,2,2,2,2, 3,3,3,3,3,3,3,3 |
|---|
| | 318 | }; |
|---|
| | 319 | |
|---|
| | 320 | if( v&0xffff0000 ) |
|---|
| | 321 | { |
|---|
| | 322 | v >>= 16; |
|---|
| | 323 | n += 16; |
|---|
| | 324 | } |
|---|
| | 325 | if( v&0xff00 ) |
|---|
| | 326 | { |
|---|
| | 327 | v >>= 8; |
|---|
| | 328 | n += 8; |
|---|
| | 329 | } |
|---|
| | 330 | if( v&0xf0 ) |
|---|
| | 331 | { |
|---|
| | 332 | v >>= 4; |
|---|
| | 333 | n += 4; |
|---|
| | 334 | } |
|---|
| | 335 | n += vlc_log2_table[v]; |
|---|
| | 336 | |
|---|
| | 337 | return n; |
|---|
| | 338 | } |
|---|
| | 339 | |
|---|
| | 340 | /* m4v_VOLParse: |
|---|
| | 341 | * TODO: |
|---|
| | 342 | * - support aspect ratio |
|---|
| | 343 | */ |
|---|
| | 344 | static int m4v_VOLParse( es_format_t *fmt, uint8_t *p_vol, int i_vol ) |
|---|
| | 345 | { |
|---|
| | 346 | bs_t s; |
|---|
| | 347 | int i_vo_type; |
|---|
| | 348 | int i_vo_ver_id; |
|---|
| | 349 | int i_ar; |
|---|
| | 350 | int i_shape; |
|---|
| | 351 | int i_time_increment_resolution; |
|---|
| 213 | | |
|---|
| 214 | | msg_Dbg( p_dec, "starcode 0x%2.2x%2.2x%2.2x%2.2x", |
|---|
| 215 | | p_vol_begin[0], p_vol_begin[1], |
|---|
| 216 | | p_vol_begin[2], p_vol_begin[3] ); |
|---|
| 217 | | |
|---|
| 218 | | if( ( p_vol_begin[3] & ~VIDEO_OBJECT_MASK ) == |
|---|
| 219 | | ( VIDEO_OBJECT_START_CODE&0xff ) ) |
|---|
| 220 | | { |
|---|
| 221 | | p_vol_end = p_vol_begin + 4; |
|---|
| 222 | | if( m4v_FindStartCode( &p_vol_end, p_end ) ) |
|---|
| 223 | | { |
|---|
| 224 | | p_vol_begin++; |
|---|
| 225 | | continue; |
|---|
| 226 | | } |
|---|
| 227 | | if( ( p_vol_end[3] & ~VIDEO_OBJECT_LAYER_MASK ) == |
|---|
| 228 | | ( VIDEO_OBJECT_LAYER_START_CODE&0xff ) ) |
|---|
| 229 | | { |
|---|
| 230 | | p_vol_end += 4; |
|---|
| 231 | | if( m4v_FindStartCode( &p_vol_end, p_end ) ) |
|---|
| 232 | | { |
|---|
| 233 | | p_vol_end = p_end; |
|---|
| 234 | | } |
|---|
| 235 | | } |
|---|
| 236 | | else |
|---|
| 237 | | { |
|---|
| 238 | | p_vol_begin++; |
|---|
| 239 | | continue; |
|---|
| 240 | | } |
|---|
| 241 | | } |
|---|
| 242 | | else if( ( p_vol_begin[3] & ~VIDEO_OBJECT_LAYER_MASK ) == |
|---|
| 243 | | ( VIDEO_OBJECT_LAYER_START_CODE&0xff) ) |
|---|
| 244 | | { |
|---|
| 245 | | p_vol_end = p_vol_begin + 4; |
|---|
| 246 | | if( m4v_FindStartCode( &p_vol_end, p_end ) ) |
|---|
| 247 | | { |
|---|
| 248 | | p_vol_end = p_end; |
|---|
| 249 | | } |
|---|
| 250 | | } |
|---|
| 251 | | |
|---|
| 252 | | if( p_vol_end != NULL && p_vol_begin < p_vol_end ) |
|---|
| 253 | | { |
|---|
| 254 | | p_dec->fmt_out.i_extra = p_vol_end - p_vol_begin; |
|---|
| 255 | | msg_Dbg( p_dec, "Found VOL" ); |
|---|
| 256 | | |
|---|
| 257 | | p_dec->fmt_out.p_extra = malloc( p_dec->fmt_out.i_extra ); |
|---|
| 258 | | memcpy( p_dec->fmt_out.p_extra, p_vol_begin, |
|---|
| 259 | | p_dec->fmt_out.i_extra ); |
|---|
| 260 | | return VLC_SUCCESS; |
|---|
| 261 | | } |
|---|
| 262 | | else |
|---|
| 263 | | { |
|---|
| 264 | | p_vol_begin++; |
|---|
| 265 | | } |
|---|
| 266 | | } |
|---|
| 267 | | |
|---|
| | 361 | p_vol++; |
|---|
| | 362 | i_vol--; |
|---|
| | 363 | if( i_vol <= 4 ) |
|---|
| | 364 | { |
|---|
| | 365 | return VLC_EGENERIC; |
|---|
| | 366 | } |
|---|
| | 367 | } |
|---|
| | 368 | |
|---|
| | 369 | /* parse the vol */ |
|---|
| | 370 | bs_init( &s, &p_vol[4], i_vol - 4 ); |
|---|
| | 371 | |
|---|
| | 372 | bs_skip( &s, 1 ); /* random access */ |
|---|
| | 373 | i_vo_type = bs_read( &s, 8 ); |
|---|
| | 374 | if( bs_read1( &s ) ) |
|---|
| | 375 | { |
|---|
| | 376 | i_vo_ver_id = bs_read( &s, 4 ); |
|---|
| | 377 | bs_skip( &s, 3 ); |
|---|
| | 378 | } |
|---|
| | 379 | else |
|---|
| | 380 | { |
|---|
| | 381 | i_vo_ver_id = 1; |
|---|
| | 382 | } |
|---|
| | 383 | i_ar = bs_read( &s, 4 ); |
|---|
| | 384 | if( i_ar == 0xf ) |
|---|
| | 385 | { |
|---|
| | 386 | int i_ar_width = bs_read( &s, 8 ); |
|---|
| | 387 | int i_ar_height= bs_read( &s, 8 ); |
|---|
| | 388 | } |
|---|
| | 389 | if( bs_read1( &s ) ) |
|---|
| | 390 | { |
|---|
| | 391 | /* vol control parameter */ |
|---|
| | 392 | int i_chroma_format = bs_read( &s, 2 ); |
|---|
| | 393 | int i_low_delay = bs_read1( &s ); |
|---|
| | 394 | |
|---|
| | 395 | if( bs_read1( &s ) ) |
|---|
| | 396 | { |
|---|
| | 397 | bs_skip( &s, 16 ); |
|---|
| | 398 | bs_skip( &s, 16 ); |
|---|
| | 399 | bs_skip( &s, 16 ); |
|---|
| | 400 | bs_skip( &s, 3 ); |
|---|
| | 401 | bs_skip( &s, 11 ); |
|---|
| | 402 | bs_skip( &s, 1 ); |
|---|
| | 403 | bs_skip( &s, 16 ); |
|---|
| | 404 | } |
|---|
| | 405 | } |
|---|
| | 406 | /* shape 0->RECT, 1->BIN, 2->BIN_ONLY, 3->GRAY */ |
|---|
| | 407 | i_shape = bs_read( &s, 2 ); |
|---|
| | 408 | if( i_shape == 3 && i_vo_ver_id != 1 ) |
|---|
| | 409 | { |
|---|
| | 410 | bs_skip( &s, 4 ); |
|---|
| | 411 | } |
|---|
| | 412 | |
|---|
| | 413 | if( !bs_read1( &s ) ) |
|---|
| | 414 | { |
|---|
| | 415 | /* marker */ |
|---|
| | 416 | return VLC_EGENERIC; |
|---|
| | 417 | } |
|---|
| | 418 | i_time_increment_resolution = bs_read( &s, 16 ); |
|---|
| | 419 | if( !bs_read1( &s ) ) |
|---|
| | 420 | { |
|---|
| | 421 | /* marker */ |
|---|
| | 422 | return VLC_EGENERIC; |
|---|
| | 423 | } |
|---|
| | 424 | |
|---|
| | 425 | if( bs_read1( &s ) ) |
|---|
| | 426 | { |
|---|
| | 427 | int i_time_increment_bits = vlc_log2( i_time_increment_resolution - 1 ) + 1; |
|---|
| | 428 | if( i_time_increment_bits < 1 ) |
|---|
| | 429 | { |
|---|
| | 430 | i_time_increment_bits = 1; |
|---|
| | 431 | } |
|---|
| | 432 | bs_skip( &s, i_time_increment_bits ); |
|---|
| | 433 | } |
|---|
| | 434 | if( i_shape == 0 ) |
|---|
| | 435 | { |
|---|
| | 436 | bs_skip( &s, 1 ); |
|---|
| | 437 | fmt->video.i_width = bs_read( &s, 13 ); |
|---|
| | 438 | bs_skip( &s, 1 ); |
|---|
| | 439 | fmt->video.i_height= bs_read( &s, 13 ); |
|---|
| | 440 | bs_skip( &s, 1 ); |
|---|
| | 441 | } |
|---|