Changeset 94431db895039165b839c35907eb21890b87cc61
- Timestamp:
- 08/14/06 23:44:15
(2 years ago)
- Author:
- Derk-Jan Hartman <hartman@videolan.org>
- git-committer:
- Derk-Jan Hartman <hartman@videolan.org> 1155591855 +0000
- git-parent:
[7cb0b7cc0d65a44147aa14fd7d7ab11936114ba0]
- git-author:
- Derk-Jan Hartman <hartman@videolan.org> 1155591855 +0000
- Message:
* Victory at last. The h264 packetizer is fixed. Thx to Haali and gibalou for the insights.
- manage private data properly
- use 4 byte startcodes
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| rbf706ca |
r94431db |
|
| 122 | 122 | /***************************************************************************** |
|---|
| 123 | 123 | * Open: probe the packetizer and return score |
|---|
| | 124 | * When opening after demux, the packetizer is only loaded AFTER the decoder |
|---|
| | 125 | * That means that what you set in fmt_out is ignored by the decoder in this special case |
|---|
| 124 | 126 | *****************************************************************************/ |
|---|
| 125 | 127 | static int Open( vlc_object_t *p_this ) |
|---|
| … | … | |
| 166 | 168 | es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); |
|---|
| 167 | 169 | p_dec->fmt_out.i_codec = VLC_FOURCC( 'h', '2', '6', '4' ); |
|---|
| 168 | | /* FIXME: FFMPEG isn't happy at all if you leave this */ |
|---|
| 169 | | if( p_dec->fmt_out.i_extra ) free( p_dec->fmt_out.p_extra ); |
|---|
| 170 | | p_dec->fmt_out.i_extra = 0; p_dec->fmt_out.p_extra = 0; |
|---|
| 171 | 170 | |
|---|
| 172 | 171 | if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'v', 'c', '1' ) ) |
|---|
| 173 | 172 | { |
|---|
| | 173 | /* This type of stream is produced by mp4 and matroska |
|---|
| | 174 | * when we want to store it in another streamformat, you need to convert |
|---|
| | 175 | * The fmt_in.p_extra should ALWAYS contain the avcC |
|---|
| | 176 | * The fmt_out.p_extra should contain all the SPS and PPS with 4 byte startcodes */ |
|---|
| 174 | 177 | uint8_t *p = &((uint8_t*)p_dec->fmt_in.p_extra)[4]; |
|---|
| 175 | 178 | int i_sps, i_pps; |
|---|
| … | … | |
| 181 | 184 | /* Read SPS */ |
|---|
| 182 | 185 | i_sps = (*p++)&0x1f; |
|---|
| 183 | | |
|---|
| 184 | 186 | for( i = 0; i < i_sps; i++ ) |
|---|
| 185 | 187 | { |
|---|
| … | … | |
| 207 | 209 | p_sys->i_avcC_length_size, i_sps, i_pps ); |
|---|
| 208 | 210 | |
|---|
| | 211 | /* FIXME: FFMPEG isn't happy at all if you leave this */ |
|---|
| | 212 | if( p_dec->fmt_out.i_extra ) free( p_dec->fmt_out.p_extra ); |
|---|
| | 213 | p_dec->fmt_out.i_extra = 0; p_dec->fmt_out.p_extra = NULL; |
|---|
| | 214 | |
|---|
| | 215 | /* Set the new extradata */ |
|---|
| | 216 | p_dec->fmt_out.i_extra = p_sys->p_pps->i_buffer + p_sys->p_sps->i_buffer; |
|---|
| | 217 | p_dec->fmt_out.p_extra = (uint8_t*)malloc( p_dec->fmt_out.i_extra ); |
|---|
| | 218 | memcpy( p_dec->fmt_out.p_extra, p_sys->p_pps->p_buffer, p_sys->p_pps->i_buffer); |
|---|
| | 219 | memcpy( p_dec->fmt_out.p_extra+p_sys->p_pps->i_buffer, p_sys->p_sps->p_buffer, p_sys->p_sps->i_buffer); |
|---|
| | 220 | |
|---|
| 209 | 221 | /* Set callback */ |
|---|
| 210 | 222 | p_dec->pf_packetize = PacketizeAVC1; |
|---|
| … | … | |
| 212 | 224 | else |
|---|
| 213 | 225 | { |
|---|
| | 226 | /* This type of stream contains data with 3 of 4 byte startcodes |
|---|
| | 227 | * The fmt_in.p_extra MAY contain SPS/PPS with 4 byte startcodes |
|---|
| | 228 | * The fmt_out.p_extra should be the same */ |
|---|
| | 229 | |
|---|
| 214 | 230 | /* Set callback */ |
|---|
| 215 | 231 | p_dec->pf_packetize = Packetize; |
|---|
| … | … | |
| 252 | 268 | /**************************************************************************** |
|---|
| 253 | 269 | * Packetize: the whole thing |
|---|
| | 270 | * Search for the startcodes 3 or more bytes |
|---|
| | 271 | * Feed ParseNALBlock ALWAYS with 4 byte startcode prepended NALs |
|---|
| 254 | 272 | ****************************************************************************/ |
|---|
| 255 | 273 | static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ) |
|---|
| … | … | |
| 267 | 285 | { |
|---|
| 268 | 286 | case STATE_NOSYNC: |
|---|
| | 287 | /* Skip untill 3 byte startcode 0 0 1 */ |
|---|
| 269 | 288 | if( block_FindStartcodeFromOffset( &p_sys->bytestream, |
|---|
| 270 | 289 | &p_sys->i_offset, p_sys->startcode+1, 3 ) == VLC_SUCCESS) |
|---|
| … | … | |
| 275 | 294 | if( p_sys->i_offset ) |
|---|
| 276 | 295 | { |
|---|
| | 296 | /* skip the data */ |
|---|
| 277 | 297 | block_SkipBytes( &p_sys->bytestream, p_sys->i_offset ); |
|---|
| 278 | 298 | p_sys->i_offset = 0; |
|---|
| … | … | |
| 289 | 309 | |
|---|
| 290 | 310 | case STATE_NEXT_SYNC: |
|---|
| 291 | | /* Find the next startcode */ |
|---|
| | 311 | /* Find the next 3 byte startcode 0 0 1*/ |
|---|
| 292 | 312 | if( block_FindStartcodeFromOffset( &p_sys->bytestream, |
|---|
| 293 | 313 | &p_sys->i_offset, p_sys->startcode+1, 3 ) != VLC_SUCCESS) |
|---|
| … | … | |
| 298 | 318 | |
|---|
| 299 | 319 | /* Get the new fragment and set the pts/dts */ |
|---|
| 300 | | p_pic = block_New( p_dec, p_sys->i_offset ); |
|---|
| | 320 | p_pic = block_New( p_dec, p_sys->i_offset +1 ); |
|---|
| 301 | 321 | p_pic->i_pts = p_sys->bytestream.p_block->i_pts; |
|---|
| 302 | 322 | p_pic->i_dts = p_sys->bytestream.p_block->i_dts; |
|---|
| 303 | | |
|---|
| 304 | | block_GetBytes( &p_sys->bytestream, p_pic->p_buffer, |
|---|
| 305 | | p_pic->i_buffer ); |
|---|
| 306 | | |
|---|
| 307 | | if( !p_pic->p_buffer[p_pic->i_buffer-1] ) p_pic->i_buffer--; |
|---|
| | 323 | /* Force 4 byte startcode 0 0 0 1 */ |
|---|
| | 324 | p_pic->p_buffer[0] = 0; |
|---|
| | 325 | |
|---|
| | 326 | block_GetBytes( &p_sys->bytestream, &p_pic->p_buffer[1], |
|---|
| | 327 | p_pic->i_buffer-1 ); |
|---|
| | 328 | |
|---|
| | 329 | /* Remove trailing 0 bytes */ |
|---|
| | 330 | while( p_pic->i_buffer && (!p_pic->p_buffer[p_pic->i_buffer-1] ) ) p_pic->i_buffer--; |
|---|
| 308 | 331 | p_sys->i_offset = 0; |
|---|
| 309 | 332 | |
|---|
| … | … | |
| 330 | 353 | |
|---|
| 331 | 354 | /**************************************************************************** |
|---|
| 332 | | * PacketizeAVC1: the whole thing |
|---|
| | 355 | * PacketizeAVC1: Takes VCL blocks of data and creates annexe B type NAL stream |
|---|
| | 356 | * Will always use 4 byte 0 0 0 1 startcodes |
|---|
| | 357 | * Should prepend the SPS and PPS to the front of the stream |
|---|
| 333 | 358 | ****************************************************************************/ |
|---|
| 334 | 359 | static block_t *PacketizeAVC1( decoder_t *p_dec, block_t **pp_block ) |
|---|
| … | … | |
| 395 | 420 | block_t *p_nal; |
|---|
| 396 | 421 | |
|---|
| 397 | | p_nal = block_New( p_dec, 3 + i_size ); |
|---|
| | 422 | p_nal = block_New( p_dec, 4 + i_size ); |
|---|
| 398 | 423 | |
|---|
| 399 | 424 | /* Add start code */ |
|---|
| 400 | 425 | p_nal->p_buffer[0] = 0x00; |
|---|
| 401 | 426 | p_nal->p_buffer[1] = 0x00; |
|---|
| 402 | | p_nal->p_buffer[2] = 0x01; |
|---|
| | 427 | p_nal->p_buffer[2] = 0x00; |
|---|
| | 428 | p_nal->p_buffer[3] = 0x01; |
|---|
| 403 | 429 | |
|---|
| 404 | 430 | /* Copy nalu */ |
|---|
| 405 | | memcpy( &p_nal->p_buffer[3], p, i_size ); |
|---|
| | 431 | memcpy( &p_nal->p_buffer[4], p, i_size ); |
|---|
| 406 | 432 | |
|---|
| 407 | 433 | return p_nal; |
|---|
| … | … | |
| 452 | 478 | |
|---|
| 453 | 479 | |
|---|
| | 480 | /***************************************************************************** |
|---|
| | 481 | * ParseNALBlock: parses annexB type NALs |
|---|
| | 482 | * All p_frag blocks are required to start with 0 0 0 1 4-byte startcode |
|---|
| | 483 | *****************************************************************************/ |
|---|
| 454 | 484 | static block_t *ParseNALBlock( decoder_t *p_dec, block_t *p_frag ) |
|---|
| 455 | 485 | { |
|---|
| … | … | |
| 457 | 487 | block_t *p_pic = NULL; |
|---|
| 458 | 488 | |
|---|
| 459 | | const int i_nal_ref_idc = (p_frag->p_buffer[3] >> 5)&0x03; |
|---|
| 460 | | const int i_nal_type = p_frag->p_buffer[3]&0x1f; |
|---|
| | 489 | const int i_nal_ref_idc = (p_frag->p_buffer[4] >> 5)&0x03; |
|---|
| | 490 | const int i_nal_type = p_frag->p_buffer[4]&0x1f; |
|---|
| 461 | 491 | |
|---|
| 462 | 492 | #define OUTPUT \ |
|---|
| … | … | |
| 494 | 524 | |
|---|
| 495 | 525 | /* do not convert the whole frame */ |
|---|
| 496 | | nal_get_decoded( &dec, &i_dec, &p_frag->p_buffer[4], |
|---|
| 497 | | __MIN( p_frag->i_buffer - 4, 60 ) ); |
|---|
| | 526 | nal_get_decoded( &dec, &i_dec, &p_frag->p_buffer[5], |
|---|
| | 527 | __MIN( p_frag->i_buffer - 5, 60 ) ); |
|---|
| 498 | 528 | bs_init( &s, dec, i_dec ); |
|---|
| 499 | 529 | |
|---|
| … | … | |
| 574 | 604 | p_sys->b_sps = VLC_TRUE; |
|---|
| 575 | 605 | |
|---|
| 576 | | nal_get_decoded( &dec, &i_dec, &p_frag->p_buffer[4], |
|---|
| 577 | | p_frag->i_buffer - 4 ); |
|---|
| | 606 | nal_get_decoded( &dec, &i_dec, &p_frag->p_buffer[5], |
|---|
| | 607 | p_frag->i_buffer - 5 ); |
|---|
| 578 | 608 | |
|---|
| 579 | 609 | bs_init( &s, dec, i_dec ); |
|---|
| … | … | |
| 686 | 716 | { |
|---|
| 687 | 717 | bs_t s; |
|---|
| 688 | | bs_init( &s, &p_frag->p_buffer[4], p_frag->i_buffer - 4 ); |
|---|
| | 718 | bs_init( &s, &p_frag->p_buffer[5], p_frag->i_buffer - 5 ); |
|---|
| 689 | 719 | |
|---|
| 690 | 720 | if( !p_sys->b_pps ) msg_Dbg( p_dec, "found NAL_PPS" ); |
|---|