diff options
author | Solomon Peachy <pizza@shaftnet.org> | 2018-12-22 20:04:28 -0500 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2018-12-22 20:12:10 -0500 |
commit | 9b9b30bd547c829157f3f83c71378f0bbd43241d (patch) | |
tree | d4f1df7303881d197e14ef8db1957705667526df /lib/rbcodec/codecs/librm | |
parent | eee3f0ce79eb0b2ae2f272e814e10e6e9524c381 (diff) | |
download | rockbox-9b9b30bd547c829157f3f83c71378f0bbd43241d.tar.gz rockbox-9b9b30bd547c829157f3f83c71378f0bbd43241d.zip |
Realmedia related codecs fixes and enhancements
* More tolerance to the file format variations.
* AC3 coded files in realaudio format are now playable
Full credit to Igor Poretsky
Change-Id: Id24e94bc00623e89fb8c80403efa92f69ab1e5d7
Diffstat (limited to 'lib/rbcodec/codecs/librm')
-rw-r--r-- | lib/rbcodec/codecs/librm/rm.c | 59 | ||||
-rw-r--r-- | lib/rbcodec/codecs/librm/rm.h | 5 |
2 files changed, 43 insertions, 21 deletions
diff --git a/lib/rbcodec/codecs/librm/rm.c b/lib/rbcodec/codecs/librm/rm.c index eabbe5d92a..e499961a7f 100644 --- a/lib/rbcodec/codecs/librm/rm.c +++ b/lib/rbcodec/codecs/librm/rm.c | |||
@@ -27,8 +27,6 @@ | |||
27 | #include "codeclib.h" | 27 | #include "codeclib.h" |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | #define SWAP(a, b) do{uint8_t SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0) | ||
31 | |||
32 | #ifdef TEST | 30 | #ifdef TEST |
33 | #include <fcntl.h> | 31 | #include <fcntl.h> |
34 | #include <unistd.h> | 32 | #include <unistd.h> |
@@ -500,17 +498,33 @@ void rm_get_packet_fd(int fd,RMContext *rmctx, RMPacket *pkt) | |||
500 | } | 498 | } |
501 | #endif /*TEST*/ | 499 | #endif /*TEST*/ |
502 | 500 | ||
501 | void rm_ac3_swap_bytes(uint8_t *buf, int bufsize) | ||
502 | { | ||
503 | uint8_t *bufptr; | ||
504 | for (bufptr = buf; bufptr < buf + bufsize - 1; bufptr += 2) | ||
505 | { | ||
506 | bufptr[0] ^= bufptr[1]; | ||
507 | bufptr[1] ^= bufptr[0]; | ||
508 | bufptr[0] ^= bufptr[1]; | ||
509 | } | ||
510 | } | ||
511 | |||
503 | int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt) | 512 | int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt) |
504 | { | 513 | { |
505 | int consumed = 0; | 514 | int consumed = 0; |
515 | int headerlen; | ||
506 | /* rockbox: comment 'set but unused' variables | 516 | /* rockbox: comment 'set but unused' variables |
507 | uint8_t unknown; | 517 | uint8_t unknown; |
508 | */ | 518 | */ |
509 | uint16_t x, place; | 519 | uint16_t x; |
510 | uint16_t sps = rmctx->sub_packet_size; | 520 | uint16_t sps = rmctx->sub_packet_size; |
511 | uint16_t h = rmctx->sub_packet_h; | 521 | uint16_t h = rmctx->sub_packet_h; |
512 | uint16_t y = rmctx->sub_packet_cnt; | 522 | uint16_t y = 0; |
513 | uint16_t w = rmctx->audio_framesize; | 523 | uint16_t w = rmctx->audio_framesize; |
524 | |||
525 | rmctx->sub_packet_cnt = 0; | ||
526 | rmctx->audio_pkt_cnt = 0; | ||
527 | |||
514 | do | 528 | do |
515 | { | 529 | { |
516 | y = rmctx->sub_packet_cnt; | 530 | y = rmctx->sub_packet_cnt; |
@@ -523,6 +537,7 @@ int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt) | |||
523 | return -1; | 537 | return -1; |
524 | } | 538 | } |
525 | 539 | ||
540 | headerlen = PACKET_HEADER_SIZE + (pkt->version ? 1 : 0); | ||
526 | pkt->length = rm_get_uint16be(*src+2); | 541 | pkt->length = rm_get_uint16be(*src+2); |
527 | pkt->stream_number = rm_get_uint16be(*src+4); | 542 | pkt->stream_number = rm_get_uint16be(*src+4); |
528 | pkt->timestamp = rm_get_uint32be(*src+6); | 543 | pkt->timestamp = rm_get_uint32be(*src+6); |
@@ -534,25 +549,27 @@ int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt) | |||
534 | pkt->flags = rm_get_uint8(*src+11); | 549 | pkt->flags = rm_get_uint8(*src+11); |
535 | 550 | ||
536 | if(pkt->version == 1) | 551 | if(pkt->version == 1) |
537 | /* unknown = */ rm_get_uint8(*src+10); | 552 | /* unknown = */ rm_get_uint8(*src+12); |
538 | 553 | ||
539 | if (pkt->flags & 2) /* keyframe */ | 554 | if (pkt->flags & 2) { /* keyframe */ |
540 | y = rmctx->sub_packet_cnt = 0; | 555 | if (y) |
556 | return consumed; | ||
557 | y = 0; | ||
558 | } | ||
541 | if (!y) | 559 | if (!y) |
542 | rmctx->audiotimestamp = pkt->timestamp; | 560 | rmctx->audiotimestamp = pkt->timestamp; |
543 | 561 | ||
544 | /* Skip packet header */ | 562 | /* Skip packet header */ |
545 | advance_buffer(src, PACKET_HEADER_SIZE); | 563 | advance_buffer(src, headerlen); |
546 | consumed += PACKET_HEADER_SIZE; | 564 | consumed += headerlen; |
547 | if (rmctx->codec_type == CODEC_COOK || rmctx->codec_type == CODEC_ATRAC) { | 565 | if (rmctx->codec_type == CODEC_COOK || rmctx->codec_type == CODEC_ATRAC) { |
548 | for(x = 0 ; x < w/sps; x++) | 566 | for(x = 0 ; x < w/sps; x++) |
549 | { | 567 | { |
550 | place = sps*(h*x+((h+1)/2)*(y&1)+(y>>1)); | 568 | pkt->frames[h*x+((h+1)/2)*(y&1)+(y>>1)] = *src; |
551 | pkt->frames[place/sps] = *src; | ||
552 | advance_buffer(src,sps); | 569 | advance_buffer(src,sps); |
553 | consumed += sps; | 570 | consumed += sps; |
554 | } | 571 | } |
555 | } | 572 | } |
556 | else if (rmctx->codec_type == CODEC_AAC) { | 573 | else if (rmctx->codec_type == CODEC_AAC) { |
557 | rmctx->sub_packet_cnt = (rm_get_uint16be(*src) & 0xf0) >> 4; | 574 | rmctx->sub_packet_cnt = (rm_get_uint16be(*src) & 0xf0) >> 4; |
558 | advance_buffer(src, 2); | 575 | advance_buffer(src, 2); |
@@ -563,22 +580,22 @@ int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt) | |||
563 | advance_buffer(src, 2); | 580 | advance_buffer(src, 2); |
564 | consumed += 2; | 581 | consumed += 2; |
565 | } | 582 | } |
566 | rmctx->audio_pkt_cnt = --rmctx->sub_packet_cnt; | 583 | rmctx->audio_pkt_cnt = rmctx->sub_packet_cnt; |
567 | } | 584 | } |
585 | break; | ||
568 | } | 586 | } |
569 | 587 | ||
570 | else if (rmctx->codec_type == CODEC_AC3) { | 588 | else if (rmctx->codec_type == CODEC_AC3) { |
571 | /* The byte order of the data is reversed from standard AC3 */ | 589 | /* The byte order of the data is reversed from standard AC3 */ |
572 | for(x = 0; x < pkt->length - PACKET_HEADER_SIZE; x+=2) { | 590 | rm_ac3_swap_bytes(*src, pkt->length - headerlen); |
573 | SWAP((*src)[0], (*src)[1]); | 591 | break; |
574 | *src += 2; | ||
575 | } | ||
576 | *src -= x; | ||
577 | } | 592 | } |
593 | else return -1; /* invalid codec type */ | ||
594 | |||
578 | rmctx->audio_pkt_cnt++; | 595 | rmctx->audio_pkt_cnt++; |
579 | }while(++(rmctx->sub_packet_cnt) < h); | 596 | }while(++(rmctx->sub_packet_cnt) < h); |
580 | 597 | ||
581 | return consumed; | 598 | return consumed; |
582 | } | 599 | } |
583 | 600 | ||
584 | #ifdef DEBUG | 601 | #ifdef DEBUG |
@@ -587,6 +604,6 @@ void dump_rm_context(RMContext *rmctx) | |||
587 | DEBUGF("block_align = %d\n", rmctx->block_align); | 604 | DEBUGF("block_align = %d\n", rmctx->block_align); |
588 | DEBUGF("nb_channels = %d\n", rmctx->nb_channels); | 605 | DEBUGF("nb_channels = %d\n", rmctx->nb_channels); |
589 | DEBUGF("sample_rate = %d\n", rmctx->sample_rate); | 606 | DEBUGF("sample_rate = %d\n", rmctx->sample_rate); |
590 | DEBUGF("bit_rate = %d\n", rmctx->bit_rate ); | 607 | DEBUGF("bit_rate = %ld\n", rmctx->bit_rate ); |
591 | } | 608 | } |
592 | #endif | 609 | #endif |
diff --git a/lib/rbcodec/codecs/librm/rm.h b/lib/rbcodec/codecs/librm/rm.h index c4a4e3a77e..47ea559f2e 100644 --- a/lib/rbcodec/codecs/librm/rm.h +++ b/lib/rbcodec/codecs/librm/rm.h | |||
@@ -25,6 +25,9 @@ | |||
25 | #include <inttypes.h> | 25 | #include <inttypes.h> |
26 | #include "bytestream.h" | 26 | #include "bytestream.h" |
27 | 27 | ||
28 | #define RM_RAW_DATASTREAM 0x0100 | ||
29 | #define RM_PKT_V1 0x0200 | ||
30 | |||
28 | #define MAX_EXTRADATA_SIZE 16 | 31 | #define MAX_EXTRADATA_SIZE 16 |
29 | #define DATA_HEADER_SIZE 18 | 32 | #define DATA_HEADER_SIZE 18 |
30 | #define PACKET_HEADER_SIZE 12 | 33 | #define PACKET_HEADER_SIZE 12 |
@@ -86,6 +89,8 @@ typedef struct rm_context | |||
86 | 89 | ||
87 | int real_parse_header(int fd, RMContext *rmctx); | 90 | int real_parse_header(int fd, RMContext *rmctx); |
88 | 91 | ||
92 | void rm_ac3_swap_bytes(uint8_t *buf, int bufsize); | ||
93 | |||
89 | /* Get a (sub_packet_h*frames_per_packet) number of audio frames from a memory buffer */ | 94 | /* Get a (sub_packet_h*frames_per_packet) number of audio frames from a memory buffer */ |
90 | int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt); | 95 | int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt); |
91 | 96 | ||