| 196 | | |
|---|
| 197 | | block_t *p_chain_out = NULL; |
|---|
| 198 | | block_t *p_block; |
|---|
| 199 | | uint8_t *p_vol = NULL; |
|---|
| 200 | | uint8_t *p_start; |
|---|
| 201 | | |
|---|
| 202 | | if( !pp_block || !*pp_block ) return NULL; |
|---|
| 203 | | |
|---|
| 204 | | p_block = *pp_block; |
|---|
| 205 | | |
|---|
| 206 | | /* Append data */ |
|---|
| 207 | | if( p_sys->i_buffer + p_block->i_buffer > p_sys->i_buffer_size ) |
|---|
| 208 | | { |
|---|
| 209 | | p_sys->i_buffer_size += p_block->i_buffer + 1024; |
|---|
| 210 | | p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size ); |
|---|
| 211 | | } |
|---|
| 212 | | memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer, |
|---|
| 213 | | p_block->i_buffer ); |
|---|
| 214 | | p_sys->i_buffer += p_block->i_buffer; |
|---|
| 215 | | |
|---|
| 216 | | if( p_sys->i_buffer > 10*1000000 ) |
|---|
| 217 | | { |
|---|
| 218 | | msg_Warn( p_dec, "reseting context" ); |
|---|
| 219 | | p_sys->i_buffer = 0; |
|---|
| 220 | | } |
|---|
| 221 | | |
|---|
| 222 | | /* Search vop */ |
|---|
| 223 | | p_start = &p_sys->p_buffer[p_sys->i_buffer - p_block->i_buffer - 4]; |
|---|
| 224 | | if( p_start < p_sys->p_buffer ) |
|---|
| 225 | | { |
|---|
| 226 | | p_start = p_sys->p_buffer; |
|---|
| 227 | | } |
|---|
| 228 | | for( ;; ) |
|---|
| 229 | | { |
|---|
| 230 | | if( m4v_FindStartCode( &p_start, &p_sys->p_buffer[p_sys->i_buffer] ) ) |
|---|
| | 221 | block_t *p_pic; |
|---|
| | 222 | mtime_t i_pts, i_dts; |
|---|
| | 223 | |
|---|
| | 224 | if( pp_block == NULL || *pp_block == NULL ) return NULL; |
|---|
| | 225 | |
|---|
| | 226 | if( (*pp_block)->i_flags & BLOCK_FLAG_DISCONTINUITY ) |
|---|
| | 227 | { |
|---|
| | 228 | p_sys->i_state = STATE_NOSYNC; |
|---|
| | 229 | if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame ); |
|---|
| | 230 | p_sys->p_frame = NULL; |
|---|
| | 231 | p_sys->pp_last = &p_sys->p_frame; |
|---|
| | 232 | block_Release( *pp_block ); |
|---|
| | 233 | return NULL; |
|---|
| | 234 | } |
|---|
| | 235 | |
|---|
| | 236 | block_BytestreamPush( &p_sys->bytestream, *pp_block ); |
|---|
| | 237 | |
|---|
| | 238 | while( 1 ) |
|---|
| | 239 | { |
|---|
| | 240 | switch( p_sys->i_state ) |
|---|
| 232 | | block_Release( p_block ); |
|---|
| 233 | | *pp_block = NULL; |
|---|
| 234 | | return p_chain_out; |
|---|
| | 242 | |
|---|
| | 243 | case STATE_NOSYNC: |
|---|
| | 244 | if( block_FindStartcodeFromOffset( &p_sys->bytestream, |
|---|
| | 245 | &p_sys->i_offset, p_sys->p_startcode, 3 ) == VLC_SUCCESS ) |
|---|
| | 246 | { |
|---|
| | 247 | p_sys->i_state = STATE_NEXT_SYNC; |
|---|
| | 248 | } |
|---|
| | 249 | |
|---|
| | 250 | if( p_sys->i_offset ) |
|---|
| | 251 | { |
|---|
| | 252 | block_SkipBytes( &p_sys->bytestream, p_sys->i_offset ); |
|---|
| | 253 | p_sys->i_offset = 0; |
|---|
| | 254 | block_BytestreamFlush( &p_sys->bytestream ); |
|---|
| | 255 | } |
|---|
| | 256 | |
|---|
| | 257 | if( p_sys->i_state != STATE_NEXT_SYNC ) |
|---|
| | 258 | { |
|---|
| | 259 | /* Need more data */ |
|---|
| | 260 | return NULL; |
|---|
| | 261 | } |
|---|
| | 262 | |
|---|
| | 263 | p_sys->i_offset = 1; /* To find next startcode */ |
|---|
| | 264 | |
|---|
| | 265 | case STATE_NEXT_SYNC: |
|---|
| | 266 | /* TODO: If p_block == NULL, flush the buffer without checking the |
|---|
| | 267 | * next sync word */ |
|---|
| | 268 | |
|---|
| | 269 | /* Find the next startcode */ |
|---|
| | 270 | if( block_FindStartcodeFromOffset( &p_sys->bytestream, |
|---|
| | 271 | &p_sys->i_offset, p_sys->p_startcode, 3 ) != VLC_SUCCESS ) |
|---|
| | 272 | { |
|---|
| | 273 | /* Need more data */ |
|---|
| | 274 | return NULL; |
|---|
| | 275 | } |
|---|
| | 276 | |
|---|
| | 277 | /* Get the new fragment and set the pts/dts */ |
|---|
| | 278 | p_pic = block_New( p_dec, p_sys->i_offset ); |
|---|
| | 279 | block_BytestreamFlush( &p_sys->bytestream ); |
|---|
| | 280 | p_pic->i_pts = i_pts = p_sys->bytestream.p_block->i_pts; |
|---|
| | 281 | p_pic->i_dts = i_dts = p_sys->bytestream.p_block->i_dts; |
|---|
| | 282 | p_pic->i_rate = p_sys->bytestream.p_block->i_rate; |
|---|
| | 283 | |
|---|
| | 284 | block_GetBytes( &p_sys->bytestream, p_pic->p_buffer, |
|---|
| | 285 | p_pic->i_buffer ); |
|---|
| | 286 | |
|---|
| | 287 | p_sys->i_offset = 0; |
|---|
| | 288 | |
|---|
| | 289 | /* Get picture if any */ |
|---|
| | 290 | if( !( p_pic = ParseMPEGBlock( p_dec, p_pic ) ) ) |
|---|
| | 291 | { |
|---|
| | 292 | p_sys->i_state = STATE_NOSYNC; |
|---|
| | 293 | break; |
|---|
| | 294 | } |
|---|
| | 295 | |
|---|
| | 296 | /* don't reuse the same timestamps several times */ |
|---|
| | 297 | if( i_pts == p_sys->bytestream.p_block->i_pts && |
|---|
| | 298 | i_dts == p_sys->bytestream.p_block->i_dts ) |
|---|
| | 299 | { |
|---|
| | 300 | p_sys->bytestream.p_block->i_pts = 0; |
|---|
| | 301 | p_sys->bytestream.p_block->i_dts = 0; |
|---|
| | 302 | } |
|---|
| | 303 | |
|---|
| | 304 | /* We've just started the stream, wait for the first PTS. |
|---|
| | 305 | * We discard here so we can still get the sequence header. */ |
|---|
| | 306 | if( p_sys->i_interpolated_pts <= 0 && |
|---|
| | 307 | p_sys->i_interpolated_dts <= 0 ) |
|---|
| | 308 | { |
|---|
| | 309 | msg_Dbg( p_dec, "need a starting pts/dts" ); |
|---|
| | 310 | p_sys->i_state = STATE_NOSYNC; |
|---|
| | 311 | block_Release( p_pic ); |
|---|
| | 312 | break; |
|---|
| | 313 | } |
|---|
| | 314 | |
|---|
| | 315 | /* When starting the stream we can have the first frame with |
|---|
| | 316 | * a null DTS (i_interpolated_pts is initialized to 0) */ |
|---|
| | 317 | if( !p_pic->i_dts ) p_pic->i_dts = p_pic->i_pts; |
|---|
| | 318 | |
|---|
| | 319 | /* So p_block doesn't get re-added several times */ |
|---|
| | 320 | *pp_block = block_BytestreamPop( &p_sys->bytestream ); |
|---|
| | 321 | |
|---|
| | 322 | p_sys->i_state = STATE_NOSYNC; |
|---|
| | 323 | |
|---|
| | 324 | return p_pic; |
|---|
| 236 | | /* fprintf( stderr, "start code=0x1%2.2x\n", p_start[3] ); */ |
|---|
| 237 | | |
|---|
| 238 | | if( p_vol ) |
|---|
| | 326 | } |
|---|
| | 327 | } |
|---|
| | 328 | |
|---|
| | 329 | /***************************************************************************** |
|---|
| | 330 | * ParseMPEGBlock: Re-assemble fragments into a block containing a picture |
|---|
| | 331 | *****************************************************************************/ |
|---|
| | 332 | static block_t *ParseMPEGBlock( decoder_t *p_dec, block_t *p_frag ) |
|---|
| | 333 | { |
|---|
| | 334 | decoder_sys_t *p_sys = p_dec->p_sys; |
|---|
| | 335 | block_t *p_pic = NULL; |
|---|
| | 336 | |
|---|
| | 337 | if( p_frag->p_buffer[3] == 0xB0 || p_frag->p_buffer[3] == 0xB1 ) |
|---|
| | 338 | { |
|---|
| | 339 | /* Remove VOS start/end code from the original stream */ |
|---|
| | 340 | block_Release( p_frag ); |
|---|
| | 341 | return NULL; |
|---|
| | 342 | } |
|---|
| | 343 | if( p_frag->p_buffer[3] >= 0x20 && p_frag->p_buffer[3] <= 0x2f ) |
|---|
| | 344 | { |
|---|
| | 345 | /* Copy the complete VOL */ |
|---|
| | 346 | p_dec->fmt_out.i_extra = p_frag->i_buffer; |
|---|
| | 347 | p_dec->fmt_out.p_extra = |
|---|
| | 348 | realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); |
|---|
| | 349 | memcpy( p_dec->fmt_out.p_extra, p_frag->p_buffer, p_frag->i_buffer ); |
|---|
| | 350 | ParseVOL( p_dec, &p_dec->fmt_out, |
|---|
| | 351 | p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); |
|---|
| | 352 | |
|---|
| | 353 | /* Remove from the original stream */ |
|---|
| | 354 | block_Release( p_frag ); |
|---|
| | 355 | return NULL; |
|---|
| | 356 | } |
|---|
| | 357 | else |
|---|
| | 358 | { |
|---|
| | 359 | if( !p_dec->fmt_out.i_extra ) |
|---|
| 260 | | if( p_sys->b_vop ) |
|---|
| 261 | | { |
|---|
| 262 | | /* Output the complete VOP we have */ |
|---|
| 263 | | int i_out = p_start - p_sys->p_buffer; |
|---|
| 264 | | block_t *p_out = block_New( p_dec, i_out ); |
|---|
| 265 | | |
|---|
| 266 | | /* extract data */ |
|---|
| 267 | | memcpy( p_out->p_buffer, p_sys->p_buffer, i_out ); |
|---|
| 268 | | if( i_out < p_sys->i_buffer ) |
|---|
| 269 | | { |
|---|
| 270 | | memmove( p_sys->p_buffer, &p_sys->p_buffer[i_out], |
|---|
| 271 | | p_sys->i_buffer - i_out ); |
|---|
| 272 | | } |
|---|
| 273 | | p_sys->i_buffer -= i_out; |
|---|
| 274 | | p_start -= i_out; |
|---|
| 275 | | |
|---|
| 276 | | p_out->i_flags = p_sys->i_flags; |
|---|
| 277 | | p_out->i_pts = p_sys->i_interpolated_pts; |
|---|
| 278 | | p_out->i_dts = p_sys->i_interpolated_dts; |
|---|
| 279 | | |
|---|
| 280 | | /* FIXME doesn't work when there is multiple VOP in one block */ |
|---|
| 281 | | if( p_block->i_dts > p_sys->i_interpolated_dts ) |
|---|
| 282 | | { |
|---|
| 283 | | p_out->i_length = p_block->i_dts - p_sys->i_interpolated_dts; |
|---|
| 284 | | } |
|---|
| 285 | | |
|---|
| 286 | | if( p_dec->fmt_out.i_extra > 0 ) |
|---|
| 287 | | { |
|---|
| 288 | | block_ChainAppend( &p_chain_out, p_out ); |
|---|
| 289 | | } |
|---|
| 290 | | else |
|---|
| 291 | | { |
|---|
| 292 | | msg_Warn( p_dec, "waiting for VOL" ); |
|---|
| 293 | | block_Release( p_out ); |
|---|
| 294 | | } |
|---|
| 295 | | |
|---|
| 296 | | p_sys->b_vop = VLC_FALSE; |
|---|
| 297 | | } |
|---|
| 298 | | |
|---|
| 299 | | if( p_start[3] >= 0x20 && p_start[3] <= 0x2f ) |
|---|
| 300 | | { |
|---|
| 301 | | /* Start of the VOL */ |
|---|
| 302 | | p_vol = p_start; |
|---|
| 303 | | } |
|---|
| 304 | | else if( p_start[3] == 0xb3 ) |
|---|
| 305 | | { |
|---|
| 306 | | /* GOP header */ |
|---|
| 307 | | } |
|---|
| 308 | | else if( p_start[3] == 0xb6 ) |
|---|
| 309 | | { |
|---|
| 310 | | /* Parse the VOP */ |
|---|
| 311 | | bs_t s; |
|---|
| 312 | | int i_modulo_time_base = 0; |
|---|
| 313 | | int i_time_increment_bits; |
|---|
| 314 | | int64_t i_time_increment, i_time_ref; |
|---|
| 315 | | |
|---|
| 316 | | /* FIXME: we don't actually check we received enough data to read |
|---|
| 317 | | * the VOP time increment. */ |
|---|
| 318 | | bs_init( &s, &p_start[4], |
|---|
| 319 | | p_sys->i_buffer - (p_start - p_sys->p_buffer) - 4 ); |
|---|
| 320 | | |
|---|
| 321 | | switch( bs_read( &s, 2 ) ) |
|---|
| 322 | | { |
|---|
| 323 | | case 0: |
|---|
| 324 | | p_sys->i_flags = BLOCK_FLAG_TYPE_I; |
|---|
| 325 | | break; |
|---|
| 326 | | case 1: |
|---|
| 327 | | p_sys->i_flags = BLOCK_FLAG_TYPE_P; |
|---|
| 328 | | break; |
|---|
| 329 | | case 2: |
|---|
| 330 | | p_sys->i_flags = BLOCK_FLAG_TYPE_B; |
|---|
| 331 | | p_sys->b_frame = VLC_TRUE; |
|---|
| 332 | | break; |
|---|
| 333 | | case 3: /* gni ? */ |
|---|
| 334 | | p_sys->i_flags = BLOCK_FLAG_TYPE_PB; |
|---|
| 335 | | break; |
|---|
| 336 | | } |
|---|
| 337 | | |
|---|
| 338 | | while( bs_read( &s, 1 ) ) i_modulo_time_base++; |
|---|
| 339 | | if( !bs_read1( &s ) ) continue; /* Marker */ |
|---|
| 340 | | |
|---|
| 341 | | /* VOP time increment */ |
|---|
| 342 | | i_time_increment_bits = vlc_log2(p_dec->p_sys->i_fps_num - 1) + 1; |
|---|
| 343 | | if( i_time_increment_bits < 1 ) i_time_increment_bits = 1; |
|---|
| 344 | | i_time_increment = bs_read( &s, i_time_increment_bits ); |
|---|
| 345 | | |
|---|
| 346 | | /* Interpolate PTS/DTS */ |
|---|
| 347 | | if( !(p_sys->i_flags & BLOCK_FLAG_TYPE_B) ) |
|---|
| 348 | | { |
|---|
| 349 | | p_sys->i_last_time_ref = p_sys->i_time_ref; |
|---|
| 350 | | p_sys->i_time_ref += |
|---|
| 351 | | (i_modulo_time_base * p_dec->p_sys->i_fps_num); |
|---|
| 352 | | i_time_ref = p_sys->i_time_ref; |
|---|
| 353 | | } |
|---|
| 354 | | else |
|---|
| 355 | | { |
|---|
| 356 | | i_time_ref = p_sys->i_last_time_ref + |
|---|
| 357 | | (i_modulo_time_base * p_dec->p_sys->i_fps_num); |
|---|
| 358 | | } |
|---|
| 359 | | |
|---|
| 360 | | if( p_dec->p_sys->i_fps_num < 5 && /* Work-around buggy streams */ |
|---|
| 361 | | p_dec->fmt_in.video.i_frame_rate > 0 && |
|---|
| 362 | | p_dec->fmt_in.video.i_frame_rate_base > 0 ) |
|---|
| 363 | | { |
|---|
| 364 | | p_sys->i_interpolated_pts += I64C(1000000) * |
|---|
| 365 | | p_dec->fmt_in.video.i_frame_rate_base * |
|---|
| 366 | | p_block->i_rate / INPUT_RATE_DEFAULT / |
|---|
| 367 | | p_dec->fmt_in.video.i_frame_rate; |
|---|
| 368 | | } |
|---|
| 369 | | else if( p_dec->p_sys->i_fps_num ) |
|---|
| 370 | | p_sys->i_interpolated_pts += |
|---|
| 371 | | ( I64C(1000000) * (i_time_ref + i_time_increment - |
|---|
| 372 | | p_sys->i_last_time - p_sys->i_last_timeincr) * |
|---|
| 373 | | p_block->i_rate / INPUT_RATE_DEFAULT / |
|---|
| 374 | | p_dec->p_sys->i_fps_num ); |
|---|
| 375 | | |
|---|
| 376 | | p_sys->i_last_time = i_time_ref; |
|---|
| 377 | | p_sys->i_last_timeincr = i_time_increment; |
|---|
| 378 | | |
|---|
| 379 | | /* Correct interpolated dts when we receive a new pts/dts */ |
|---|
| 380 | | if( p_block->i_pts > 0 ) |
|---|
| 381 | | p_sys->i_interpolated_pts = p_block->i_pts; |
|---|
| 382 | | if( p_block->i_dts > 0 ) |
|---|
| 383 | | p_sys->i_interpolated_dts = p_block->i_dts; |
|---|
| 384 | | |
|---|
| 385 | | if( (p_sys->i_flags & BLOCK_FLAG_TYPE_B) || !p_sys->b_frame ) |
|---|
| 386 | | { |
|---|
| 387 | | /* Trivial case (DTS == PTS) */ |
|---|
| 388 | | |
|---|
| 389 | | p_sys->i_interpolated_dts = p_sys->i_interpolated_pts; |
|---|
| 390 | | |
|---|
| 391 | | if( p_block->i_pts > 0 ) |
|---|
| 392 | | p_sys->i_interpolated_dts = p_block->i_pts; |
|---|
| 393 | | if( p_block->i_dts > 0 ) |
|---|
| 394 | | p_sys->i_interpolated_dts = p_block->i_dts; |
|---|
| 395 | | |
|---|
| 396 | | p_sys->i_interpolated_pts = p_sys->i_interpolated_dts; |
|---|
| 397 | | } |
|---|
| 398 | | else |
|---|
| 399 | | { |
|---|
| 400 | | if( p_sys->i_last_ref_pts > 0 ) |
|---|
| 401 | | p_sys->i_interpolated_dts = p_sys->i_last_ref_pts; |
|---|
| 402 | | |
|---|
| 403 | | p_sys->i_last_ref_pts = p_sys->i_interpolated_pts; |
|---|
| 404 | | } |
|---|
| 405 | | |
|---|
| 406 | | p_sys->b_vop = VLC_TRUE; |
|---|
| 407 | | |
|---|
| 408 | | /* Don't re-use the same PTS/DTS twice */ |
|---|
| 409 | | p_block->i_pts = p_block->i_dts = 0; |
|---|
| 410 | | } |
|---|
| 411 | | |
|---|
| 412 | | p_start += 4; /* Next */ |
|---|
| 413 | | } |
|---|
| | 365 | |
|---|
| | 366 | /* Append the block */ |
|---|
| | 367 | block_ChainLastAppend( &p_sys->pp_last, p_frag ); |
|---|
| | 368 | } |
|---|
| | 369 | |
|---|
| | 370 | if( p_frag->p_buffer[3] == 0xb6 && |
|---|
| | 371 | ParseVOP( p_dec, p_frag ) == VLC_SUCCESS ) |
|---|
| | 372 | { |
|---|
| | 373 | /* We are dealing with a VOP */ |
|---|
| | 374 | p_pic = block_ChainGather( p_sys->p_frame ); |
|---|
| | 375 | p_pic->i_pts = p_sys->i_interpolated_pts; |
|---|
| | 376 | p_pic->i_dts = p_sys->i_interpolated_dts; |
|---|
| | 377 | |
|---|
| | 378 | /* Reset context */ |
|---|
| | 379 | p_sys->p_frame = NULL; |
|---|
| | 380 | p_sys->pp_last = &p_sys->p_frame; |
|---|
| | 381 | } |
|---|
| | 382 | |
|---|
| | 383 | return p_pic; |
|---|
| | 480 | |
|---|
| | 481 | static int ParseVOP( decoder_t *p_dec, block_t *p_vop ) |
|---|
| | 482 | { |
|---|
| | 483 | decoder_sys_t *p_sys = p_dec->p_sys; |
|---|
| | 484 | int64_t i_time_increment, i_time_ref; |
|---|
| | 485 | int i_modulo_time_base = 0, i_time_increment_bits; |
|---|
| | 486 | bs_t s; |
|---|
| | 487 | |
|---|
| | 488 | bs_init( &s, &p_vop->p_buffer[4], p_vop->i_buffer - 4 ); |
|---|
| | 489 | |
|---|
| | 490 | switch( bs_read( &s, 2 ) ) |
|---|
| | 491 | { |
|---|
| | 492 | case 0: |
|---|
| | 493 | p_sys->i_flags = BLOCK_FLAG_TYPE_I; |
|---|
| | 494 | break; |
|---|
| | 495 | case 1: |
|---|
| | 496 | p_sys->i_flags = BLOCK_FLAG_TYPE_P; |
|---|
| | 497 | break; |
|---|
| | 498 | case 2: |
|---|
| | 499 | p_sys->i_flags = BLOCK_FLAG_TYPE_B; |
|---|
| | 500 | p_sys->b_frame = VLC_TRUE; |
|---|
| | 501 | break; |
|---|
| | 502 | case 3: /* gni ? */ |
|---|
| | 503 | p_sys->i_flags = BLOCK_FLAG_TYPE_PB; |
|---|
| | 504 | break; |
|---|
| | 505 | } |
|---|
| | 506 | |
|---|
| | 507 | while( bs_read( &s, 1 ) ) i_modulo_time_base++; |
|---|
| | 508 | if( !bs_read1( &s ) ) return VLC_EGENERIC; /* Marker */ |
|---|
| | 509 | |
|---|
| | 510 | /* VOP time increment */ |
|---|
| | 511 | i_time_increment_bits = vlc_log2(p_dec->p_sys->i_fps_num - 1) + 1; |
|---|
| | 512 | if( i_time_increment_bits < 1 ) i_time_increment_bits = 1; |
|---|
| | 513 | i_time_increment = bs_read( &s, i_time_increment_bits ); |
|---|
| | 514 | |
|---|
| | 515 | /* Interpolate PTS/DTS */ |
|---|
| | 516 | if( !(p_sys->i_flags & BLOCK_FLAG_TYPE_B) ) |
|---|
| | 517 | { |
|---|
| | 518 | p_sys->i_last_time_ref = p_sys->i_time_ref; |
|---|
| | 519 | p_sys->i_time_ref += |
|---|
| | 520 | (i_modulo_time_base * p_dec->p_sys->i_fps_num); |
|---|
| | 521 | i_time_ref = p_sys->i_time_ref; |
|---|
| | 522 | } |
|---|
| | 523 | else |
|---|
| | 524 | { |
|---|
| | 525 | i_time_ref = p_sys->i_last_time_ref + |
|---|
| | 526 | (i_modulo_time_base * p_dec->p_sys->i_fps_num); |
|---|
| | 527 | } |
|---|
| | 528 | |
|---|
| | 529 | #if 0 |
|---|
| | 530 | msg_Err( p_dec, "interp pts/dts (%lli,%lli), pts/dts (%lli,%lli)", |
|---|
| | 531 | p_sys->i_interpolated_pts, p_sys->i_interpolated_dts, |
|---|
| | 532 | p_vop->i_pts, p_vop->i_dts ); |
|---|
| | 533 | #endif |
|---|
| | 534 | |
|---|
| | 535 | if( p_dec->p_sys->i_fps_num < 5 && /* Work-around buggy streams */ |
|---|
| | 536 | p_dec->fmt_in.video.i_frame_rate > 0 && |
|---|
| | 537 | p_dec->fmt_in.video.i_frame_rate_base > 0 ) |
|---|
| | 538 | { |
|---|
| | 539 | p_sys->i_interpolated_pts += I64C(1000000) * |
|---|
| | 540 | p_dec->fmt_in.video.i_frame_rate_base * |
|---|
| | 541 | p_vop->i_rate / INPUT_RATE_DEFAULT / |
|---|
| | 542 | p_dec->fmt_in.video.i_frame_rate; |
|---|
| | 543 | } |
|---|
| | 544 | else if( p_dec->p_sys->i_fps_num ) |
|---|
| | 545 | p_sys->i_interpolated_pts += |
|---|
| | 546 | ( I64C(1000000) * (i_time_ref + i_time_increment - |
|---|
| | 547 | p_sys->i_last_time - p_sys->i_last_timeincr) * |
|---|
| | 548 | p_vop->i_rate / INPUT_RATE_DEFAULT / |
|---|
| | 549 | p_dec->p_sys->i_fps_num ); |
|---|
| | 550 | |
|---|
| | 551 | p_sys->i_last_time = i_time_ref; |
|---|
| | 552 | p_sys->i_last_timeincr = i_time_increment; |
|---|
| | 553 | |
|---|
| | 554 | /* Correct interpolated dts when we receive a new pts/dts */ |
|---|
| | 555 | if( p_vop->i_pts > 0 ) |
|---|
| | 556 | p_sys->i_interpolated_pts = p_vop->i_pts; |
|---|
| | 557 | if( p_vop->i_dts > 0 ) |
|---|
| | 558 | p_sys->i_interpolated_dts = p_vop->i_dts; |
|---|
| | 559 | |
|---|
| | 560 | if( (p_sys->i_flags & BLOCK_FLAG_TYPE_B) || !p_sys->b_frame ) |
|---|
| | 561 | { |
|---|
| | 562 | /* Trivial case (DTS == PTS) */ |
|---|
| | 563 | |
|---|
| | 564 | p_sys->i_interpolated_dts = p_sys->i_interpolated_pts; |
|---|
| | 565 | |
|---|
| | 566 | if( p_vop->i_pts > 0 ) |
|---|
| | 567 | p_sys->i_interpolated_dts = p_vop->i_pts; |
|---|
| | 568 | if( p_vop->i_dts > 0 ) |
|---|
| | 569 | p_sys->i_interpolated_dts = p_vop->i_dts; |
|---|
| | 570 | |
|---|
| | 571 | p_sys->i_interpolated_pts = p_sys->i_interpolated_dts; |
|---|
| | 572 | } |
|---|
| | 573 | else |
|---|
| | 574 | { |
|---|
| | 575 | if( p_sys->i_last_ref_pts > 0 ) |
|---|
| | 576 | p_sys->i_interpolated_dts = p_sys->i_last_ref_pts; |
|---|
| | 577 | |
|---|
| | 578 | p_sys->i_last_ref_pts = p_sys->i_interpolated_pts; |
|---|
| | 579 | } |
|---|
| | 580 | |
|---|
| | 581 | return VLC_SUCCESS; |
|---|
| | 582 | } |
|---|
| | 583 | |
|---|
| | 584 | /* look at ffmpeg av_log2 ;) */ |
|---|
| | 585 | static int vlc_log2( unsigned int v ) |
|---|
| | 586 | { |
|---|
| | 587 | int n = 0; |
|---|
| | 588 | static const int vlc_log2_table[16] = |
|---|
| | 589 | { |
|---|
| | 590 | 0,0,1,1,2,2,2,2, 3,3,3,3,3,3,3,3 |
|---|
| | 591 | }; |
|---|
| | 592 | |
|---|
| | 593 | if( v&0xffff0000 ) |
|---|
| | 594 | { |
|---|
| | 595 | v >>= 16; |
|---|
| | 596 | n += 16; |
|---|
| | 597 | } |
|---|
| | 598 | if( v&0xff00 ) |
|---|
| | 599 | { |
|---|
| | 600 | v >>= 8; |
|---|
| | 601 | n += 8; |
|---|
| | 602 | } |
|---|
| | 603 | if( v&0xf0 ) |
|---|
| | 604 | { |
|---|
| | 605 | v >>= 4; |
|---|
| | 606 | n += 4; |
|---|
| | 607 | } |
|---|
| | 608 | n += vlc_log2_table[v]; |
|---|
| | 609 | |
|---|
| | 610 | return n; |
|---|
| | 611 | } |
|---|