You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
5.0KB

  1. /*
  2. * Copyright (c) 2018 Paul B Mahol
  3. *
  4. * This file is part of FFmpeg.
  5. *
  6. * FFmpeg is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * FFmpeg is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with FFmpeg; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include "avcodec.h"
  21. #include "bsf_internal.h"
  22. #include "get_bits.h"
  23. #include "mlp_parse.h"
  24. #include "mlp.h"
  25. typedef struct AccessUnit {
  26. uint8_t bits[4];
  27. uint16_t offset;
  28. uint16_t optional;
  29. } AccessUnit;
  30. typedef struct TrueHDCoreContext {
  31. MLPHeaderInfo hdr;
  32. } TrueHDCoreContext;
  33. static int truehd_core_filter(AVBSFContext *ctx, AVPacket *pkt)
  34. {
  35. TrueHDCoreContext *s = ctx->priv_data;
  36. GetBitContext gbc;
  37. AccessUnit units[MAX_SUBSTREAMS];
  38. int ret, i, last_offset = 0;
  39. int in_size, out_size;
  40. int have_header = 0;
  41. int substream_bytes = 0;
  42. int end;
  43. ret = ff_bsf_get_packet_ref(ctx, pkt);
  44. if (ret < 0)
  45. return ret;
  46. if (pkt->size < 4) {
  47. ret = AVERROR_INVALIDDATA;
  48. goto fail;
  49. }
  50. in_size = (AV_RB16(pkt->data) & 0xFFF) * 2;
  51. if (in_size < 4 || in_size > pkt->size) {
  52. ret = AVERROR_INVALIDDATA;
  53. goto fail;
  54. }
  55. ret = init_get_bits8(&gbc, pkt->data + 4, pkt->size - 4);
  56. if (ret < 0)
  57. goto fail;
  58. if (show_bits_long(&gbc, 32) == 0xf8726fba) {
  59. if ((ret = ff_mlp_read_major_sync(ctx, &s->hdr, &gbc)) < 0)
  60. goto fail;
  61. have_header = 1;
  62. }
  63. if (s->hdr.num_substreams > MAX_SUBSTREAMS) {
  64. ret = AVERROR_INVALIDDATA;
  65. goto fail;
  66. }
  67. for (i = 0; i < s->hdr.num_substreams; i++) {
  68. for (int j = 0; j < 4; j++)
  69. units[i].bits[j] = get_bits1(&gbc);
  70. units[i].offset = get_bits(&gbc, 12);
  71. if (i < 3) {
  72. last_offset = units[i].offset * 2;
  73. substream_bytes += 2;
  74. }
  75. if (units[i].bits[0]) {
  76. units[i].optional = get_bits(&gbc, 16);
  77. if (i < 3)
  78. substream_bytes += 2;
  79. }
  80. }
  81. end = get_bits_count(&gbc) >> 3;
  82. out_size = end + 4 + last_offset;
  83. if (out_size < in_size) {
  84. int bpos = 0, reduce = end - have_header * 28 - substream_bytes;
  85. uint16_t parity_nibble, dts = AV_RB16(pkt->data + 2);
  86. uint16_t auheader;
  87. uint8_t header[28];
  88. av_assert1(reduce >= 0 && reduce % 2 == 0);
  89. if (have_header) {
  90. memcpy(header, pkt->data + 4, 28);
  91. header[16] = (header[16] & 0x0c) | (FFMIN(s->hdr.num_substreams, 3) << 4);
  92. header[17] &= 0x7f;
  93. header[25] &= 0xfe;
  94. AV_WL16(header + 26, ff_mlp_checksum16(header, 26));
  95. }
  96. pkt->data += reduce;
  97. out_size -= reduce;
  98. pkt->size = out_size;
  99. ret = av_packet_make_writable(pkt);
  100. if (ret < 0)
  101. goto fail;
  102. AV_WB16(pkt->data + 2, dts);
  103. parity_nibble = dts;
  104. parity_nibble ^= out_size / 2;
  105. for (i = 0; i < FFMIN(s->hdr.num_substreams, 3); i++) {
  106. uint16_t substr_hdr = 0;
  107. substr_hdr |= (units[i].bits[0] << 15);
  108. substr_hdr |= (units[i].bits[1] << 14);
  109. substr_hdr |= (units[i].bits[2] << 13);
  110. substr_hdr |= (units[i].bits[3] << 12);
  111. substr_hdr |= units[i].offset;
  112. AV_WB16(pkt->data + have_header * 28 + 4 + bpos, substr_hdr);
  113. parity_nibble ^= substr_hdr;
  114. bpos += 2;
  115. if (units[i].bits[0]) {
  116. AV_WB16(pkt->data + have_header * 28 + 4 + bpos, units[i].optional);
  117. parity_nibble ^= units[i].optional;
  118. bpos += 2;
  119. }
  120. }
  121. parity_nibble ^= parity_nibble >> 8;
  122. parity_nibble ^= parity_nibble >> 4;
  123. parity_nibble &= 0xF;
  124. auheader = (parity_nibble ^ 0xF) << 12;
  125. auheader |= (out_size / 2) & 0x0fff;
  126. AV_WB16(pkt->data, auheader);
  127. if (have_header)
  128. memcpy(pkt->data + 4, header, 28);
  129. }
  130. fail:
  131. if (ret < 0)
  132. av_packet_unref(pkt);
  133. return ret;
  134. }
  135. static void truehd_core_flush(AVBSFContext *ctx)
  136. {
  137. TrueHDCoreContext *s = ctx->priv_data;
  138. memset(&s->hdr, 0, sizeof(s->hdr));
  139. }
  140. static const enum AVCodecID codec_ids[] = {
  141. AV_CODEC_ID_TRUEHD, AV_CODEC_ID_NONE,
  142. };
  143. const AVBitStreamFilter ff_truehd_core_bsf = {
  144. .name = "truehd_core",
  145. .priv_data_size = sizeof(TrueHDCoreContext),
  146. .filter = truehd_core_filter,
  147. .flush = truehd_core_flush,
  148. .codec_ids = codec_ids,
  149. };