Mercurial > libavcodec.hg
comparison parser.c @ 4941:c3ee5c30c297 libavcodec
move aac and ac3 parsers in their own files
| author | aurel |
|---|---|
| date | Tue, 08 May 2007 23:25:31 +0000 |
| parents | 0d1cc37d9430 |
| children | 25cd2084129a |
comparison
equal
deleted
inserted
replaced
| 4940:f8e21b3014f7 | 4941:c3ee5c30c297 |
|---|---|
| 309 if(state == 0x1B3 || state == 0x1B6) | 309 if(state == 0x1B3 || state == 0x1B6) |
| 310 return i-3; | 310 return i-3; |
| 311 } | 311 } |
| 312 return 0; | 312 return 0; |
| 313 } | 313 } |
| 314 | |
| 315 /*************************/ | |
| 316 | |
| 317 #if defined(CONFIG_AC3_PARSER) || defined(CONFIG_AAC_PARSER) | |
| 318 /* also used for ADTS AAC */ | |
| 319 typedef struct AC3ParseContext { | |
| 320 uint8_t *inbuf_ptr; | |
| 321 int frame_size; | |
| 322 int header_size; | |
| 323 int (*sync)(const uint8_t *buf, int *channels, int *sample_rate, | |
| 324 int *bit_rate, int *samples); | |
| 325 uint8_t inbuf[8192]; /* input buffer */ | |
| 326 } AC3ParseContext; | |
| 327 | |
| 328 #define AC3_HEADER_SIZE 7 | |
| 329 #define AAC_HEADER_SIZE 7 | |
| 330 | |
| 331 #ifdef CONFIG_AC3_PARSER | |
| 332 | |
| 333 static const uint8_t eac3_blocks[4] = { | |
| 334 1, 2, 3, 6 | |
| 335 }; | |
| 336 | |
| 337 #endif /* CONFIG_AC3_PARSER */ | |
| 338 | |
| 339 #ifdef CONFIG_AAC_PARSER | |
| 340 static const int aac_sample_rates[16] = { | |
| 341 96000, 88200, 64000, 48000, 44100, 32000, | |
| 342 24000, 22050, 16000, 12000, 11025, 8000, 7350 | |
| 343 }; | |
| 344 | |
| 345 static const int aac_channels[8] = { | |
| 346 0, 1, 2, 3, 4, 5, 6, 8 | |
| 347 }; | |
| 348 #endif | |
| 349 | |
| 350 #ifdef CONFIG_AC3_PARSER | |
| 351 int ff_ac3_parse_header(const uint8_t buf[7], AC3HeaderInfo *hdr) | |
| 352 { | |
| 353 GetBitContext gbc; | |
| 354 | |
| 355 memset(hdr, 0, sizeof(*hdr)); | |
| 356 | |
| 357 init_get_bits(&gbc, buf, 54); | |
| 358 | |
| 359 hdr->sync_word = get_bits(&gbc, 16); | |
| 360 if(hdr->sync_word != 0x0B77) | |
| 361 return -1; | |
| 362 | |
| 363 /* read ahead to bsid to make sure this is AC-3, not E-AC-3 */ | |
| 364 hdr->bsid = show_bits_long(&gbc, 29) & 0x1F; | |
| 365 if(hdr->bsid > 10) | |
| 366 return -2; | |
| 367 | |
| 368 hdr->crc1 = get_bits(&gbc, 16); | |
| 369 hdr->fscod = get_bits(&gbc, 2); | |
| 370 if(hdr->fscod == 3) | |
| 371 return -3; | |
| 372 | |
| 373 hdr->frmsizecod = get_bits(&gbc, 6); | |
| 374 if(hdr->frmsizecod > 37) | |
| 375 return -4; | |
| 376 | |
| 377 skip_bits(&gbc, 5); // skip bsid, already got it | |
| 378 | |
| 379 hdr->bsmod = get_bits(&gbc, 3); | |
| 380 hdr->acmod = get_bits(&gbc, 3); | |
| 381 if((hdr->acmod & 1) && hdr->acmod != 1) { | |
| 382 hdr->cmixlev = get_bits(&gbc, 2); | |
| 383 } | |
| 384 if(hdr->acmod & 4) { | |
| 385 hdr->surmixlev = get_bits(&gbc, 2); | |
| 386 } | |
| 387 if(hdr->acmod == 2) { | |
| 388 hdr->dsurmod = get_bits(&gbc, 2); | |
| 389 } | |
| 390 hdr->lfeon = get_bits1(&gbc); | |
| 391 | |
| 392 hdr->halfratecod = FFMAX(hdr->bsid, 8) - 8; | |
| 393 hdr->sample_rate = ff_ac3_freqs[hdr->fscod] >> hdr->halfratecod; | |
| 394 hdr->bit_rate = (ff_ac3_bitratetab[hdr->frmsizecod>>1] * 1000) >> hdr->halfratecod; | |
| 395 hdr->channels = ff_ac3_channels[hdr->acmod] + hdr->lfeon; | |
| 396 hdr->frame_size = ff_ac3_frame_sizes[hdr->frmsizecod][hdr->fscod] * 2; | |
| 397 | |
| 398 return 0; | |
| 399 } | |
| 400 | |
| 401 static int ac3_sync(const uint8_t *buf, int *channels, int *sample_rate, | |
| 402 int *bit_rate, int *samples) | |
| 403 { | |
| 404 int err; | |
| 405 unsigned int fscod, acmod, bsid, lfeon; | |
| 406 unsigned int strmtyp, substreamid, frmsiz, fscod2, numblkscod; | |
| 407 GetBitContext bits; | |
| 408 AC3HeaderInfo hdr; | |
| 409 | |
| 410 err = ff_ac3_parse_header(buf, &hdr); | |
| 411 | |
| 412 if(err < 0 && err != -2) | |
| 413 return 0; | |
| 414 | |
| 415 bsid = hdr.bsid; | |
| 416 if(bsid <= 10) { /* Normal AC-3 */ | |
| 417 *sample_rate = hdr.sample_rate; | |
| 418 *bit_rate = hdr.bit_rate; | |
| 419 *channels = hdr.channels; | |
| 420 *samples = AC3_FRAME_SIZE; | |
| 421 return hdr.frame_size; | |
| 422 } else if (bsid > 10 && bsid <= 16) { /* Enhanced AC-3 */ | |
| 423 init_get_bits(&bits, &buf[2], (AC3_HEADER_SIZE-2) * 8); | |
| 424 strmtyp = get_bits(&bits, 2); | |
| 425 substreamid = get_bits(&bits, 3); | |
| 426 | |
| 427 if (strmtyp != 0 || substreamid != 0) | |
| 428 return 0; /* Currently don't support additional streams */ | |
| 429 | |
| 430 frmsiz = get_bits(&bits, 11) + 1; | |
| 431 fscod = get_bits(&bits, 2); | |
| 432 if (fscod == 3) { | |
| 433 fscod2 = get_bits(&bits, 2); | |
| 434 numblkscod = 3; | |
| 435 | |
| 436 if(fscod2 == 3) | |
| 437 return 0; | |
| 438 | |
| 439 *sample_rate = ff_ac3_freqs[fscod2] / 2; | |
| 440 } else { | |
| 441 numblkscod = get_bits(&bits, 2); | |
| 442 | |
| 443 *sample_rate = ff_ac3_freqs[fscod]; | |
| 444 } | |
| 445 | |
| 446 acmod = get_bits(&bits, 3); | |
| 447 lfeon = get_bits1(&bits); | |
| 448 | |
| 449 *samples = eac3_blocks[numblkscod] * 256; | |
| 450 *bit_rate = frmsiz * (*sample_rate) * 16 / (*samples); | |
| 451 *channels = ff_ac3_channels[acmod] + lfeon; | |
| 452 | |
| 453 return frmsiz * 2; | |
| 454 } | |
| 455 | |
| 456 /* Unsupported bitstream version */ | |
| 457 return 0; | |
| 458 } | |
| 459 #endif /* CONFIG_AC3_PARSER */ | |
| 460 | |
| 461 #ifdef CONFIG_AAC_PARSER | |
| 462 static int aac_sync(const uint8_t *buf, int *channels, int *sample_rate, | |
| 463 int *bit_rate, int *samples) | |
| 464 { | |
| 465 GetBitContext bits; | |
| 466 int size, rdb, ch, sr; | |
| 467 | |
| 468 init_get_bits(&bits, buf, AAC_HEADER_SIZE * 8); | |
| 469 | |
| 470 if(get_bits(&bits, 12) != 0xfff) | |
| 471 return 0; | |
| 472 | |
| 473 skip_bits1(&bits); /* id */ | |
| 474 skip_bits(&bits, 2); /* layer */ | |
| 475 skip_bits1(&bits); /* protection_absent */ | |
| 476 skip_bits(&bits, 2); /* profile_objecttype */ | |
| 477 sr = get_bits(&bits, 4); /* sample_frequency_index */ | |
| 478 if(!aac_sample_rates[sr]) | |
| 479 return 0; | |
| 480 skip_bits1(&bits); /* private_bit */ | |
| 481 ch = get_bits(&bits, 3); /* channel_configuration */ | |
| 482 if(!aac_channels[ch]) | |
| 483 return 0; | |
| 484 skip_bits1(&bits); /* original/copy */ | |
| 485 skip_bits1(&bits); /* home */ | |
| 486 | |
| 487 /* adts_variable_header */ | |
| 488 skip_bits1(&bits); /* copyright_identification_bit */ | |
| 489 skip_bits1(&bits); /* copyright_identification_start */ | |
| 490 size = get_bits(&bits, 13); /* aac_frame_length */ | |
| 491 skip_bits(&bits, 11); /* adts_buffer_fullness */ | |
| 492 rdb = get_bits(&bits, 2); /* number_of_raw_data_blocks_in_frame */ | |
| 493 | |
| 494 *channels = aac_channels[ch]; | |
| 495 *sample_rate = aac_sample_rates[sr]; | |
| 496 *samples = (rdb + 1) * 1024; | |
| 497 *bit_rate = size * 8 * *sample_rate / *samples; | |
| 498 | |
| 499 return size; | |
| 500 } | |
| 501 #endif /* CONFIG_AAC_PARSER */ | |
| 502 | |
| 503 #ifdef CONFIG_AC3_PARSER | |
| 504 static int ac3_parse_init(AVCodecParserContext *s1) | |
| 505 { | |
| 506 AC3ParseContext *s = s1->priv_data; | |
| 507 s->inbuf_ptr = s->inbuf; | |
| 508 s->header_size = AC3_HEADER_SIZE; | |
| 509 s->sync = ac3_sync; | |
| 510 return 0; | |
| 511 } | |
| 512 #endif | |
| 513 | |
| 514 #ifdef CONFIG_AAC_PARSER | |
| 515 static int aac_parse_init(AVCodecParserContext *s1) | |
| 516 { | |
| 517 AC3ParseContext *s = s1->priv_data; | |
| 518 s->inbuf_ptr = s->inbuf; | |
| 519 s->header_size = AAC_HEADER_SIZE; | |
| 520 s->sync = aac_sync; | |
| 521 return 0; | |
| 522 } | |
| 523 #endif | |
| 524 | |
| 525 /* also used for ADTS AAC */ | |
| 526 static int ac3_parse(AVCodecParserContext *s1, | |
| 527 AVCodecContext *avctx, | |
| 528 const uint8_t **poutbuf, int *poutbuf_size, | |
| 529 const uint8_t *buf, int buf_size) | |
| 530 { | |
| 531 AC3ParseContext *s = s1->priv_data; | |
| 532 const uint8_t *buf_ptr; | |
| 533 int len, sample_rate, bit_rate, channels, samples; | |
| 534 | |
| 535 *poutbuf = NULL; | |
| 536 *poutbuf_size = 0; | |
| 537 | |
| 538 buf_ptr = buf; | |
| 539 while (buf_size > 0) { | |
| 540 len = s->inbuf_ptr - s->inbuf; | |
| 541 if (s->frame_size == 0) { | |
| 542 /* no header seen : find one. We need at least s->header_size | |
| 543 bytes to parse it */ | |
| 544 len = FFMIN(s->header_size - len, buf_size); | |
| 545 | |
| 546 memcpy(s->inbuf_ptr, buf_ptr, len); | |
| 547 buf_ptr += len; | |
| 548 s->inbuf_ptr += len; | |
| 549 buf_size -= len; | |
| 550 if ((s->inbuf_ptr - s->inbuf) == s->header_size) { | |
| 551 len = s->sync(s->inbuf, &channels, &sample_rate, &bit_rate, | |
| 552 &samples); | |
| 553 if (len == 0) { | |
| 554 /* no sync found : move by one byte (inefficient, but simple!) */ | |
| 555 memmove(s->inbuf, s->inbuf + 1, s->header_size - 1); | |
| 556 s->inbuf_ptr--; | |
| 557 } else { | |
| 558 s->frame_size = len; | |
| 559 /* update codec info */ | |
| 560 avctx->sample_rate = sample_rate; | |
| 561 /* set channels,except if the user explicitly requests 1 or 2 channels, XXX/FIXME this is a bit ugly */ | |
| 562 if(avctx->codec_id == CODEC_ID_AC3){ | |
| 563 if(avctx->channels!=1 && avctx->channels!=2){ | |
| 564 avctx->channels = channels; | |
| 565 } | |
| 566 } else { | |
| 567 avctx->channels = channels; | |
| 568 } | |
| 569 avctx->bit_rate = bit_rate; | |
| 570 avctx->frame_size = samples; | |
| 571 } | |
| 572 } | |
| 573 } else { | |
| 574 len = FFMIN(s->frame_size - len, buf_size); | |
| 575 | |
| 576 memcpy(s->inbuf_ptr, buf_ptr, len); | |
| 577 buf_ptr += len; | |
| 578 s->inbuf_ptr += len; | |
| 579 buf_size -= len; | |
| 580 | |
| 581 if(s->inbuf_ptr - s->inbuf == s->frame_size){ | |
| 582 *poutbuf = s->inbuf; | |
| 583 *poutbuf_size = s->frame_size; | |
| 584 s->inbuf_ptr = s->inbuf; | |
| 585 s->frame_size = 0; | |
| 586 break; | |
| 587 } | |
| 588 } | |
| 589 } | |
| 590 return buf_ptr - buf; | |
| 591 } | |
| 592 #endif /* CONFIG_AC3_PARSER || CONFIG_AAC_PARSER */ | |
| 593 | |
| 594 #ifdef CONFIG_AC3_PARSER | |
| 595 AVCodecParser ac3_parser = { | |
| 596 { CODEC_ID_AC3 }, | |
| 597 sizeof(AC3ParseContext), | |
| 598 ac3_parse_init, | |
| 599 ac3_parse, | |
| 600 NULL, | |
| 601 }; | |
| 602 #endif | |
| 603 #ifdef CONFIG_AAC_PARSER | |
| 604 AVCodecParser aac_parser = { | |
| 605 { CODEC_ID_AAC }, | |
| 606 sizeof(AC3ParseContext), | |
| 607 aac_parse_init, | |
| 608 ac3_parse, | |
| 609 NULL, | |
| 610 }; | |
| 611 #endif |
