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.

217 lines
6.4KB

  1. /*
  2. * MLP parser
  3. * Copyright (c) 2007 Ian Caulfield
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. /**
  22. * @file
  23. * MLP parser
  24. */
  25. #include <stdint.h>
  26. #include "libavutil/internal.h"
  27. #include "get_bits.h"
  28. #include "parser.h"
  29. #include "mlp_parse.h"
  30. #include "mlp.h"
  31. typedef struct MLPParseContext
  32. {
  33. ParseContext pc;
  34. int bytes_left;
  35. int in_sync;
  36. int num_substreams;
  37. } MLPParseContext;
  38. static av_cold int mlp_init(AVCodecParserContext *s)
  39. {
  40. ff_mlp_init_crc();
  41. return 0;
  42. }
  43. static int mlp_parse(AVCodecParserContext *s,
  44. AVCodecContext *avctx,
  45. const uint8_t **poutbuf, int *poutbuf_size,
  46. const uint8_t *buf, int buf_size)
  47. {
  48. MLPParseContext *mp = s->priv_data;
  49. int sync_present;
  50. uint8_t parity_bits;
  51. int next;
  52. int ret;
  53. int i, p = 0;
  54. s->key_frame = 0;
  55. *poutbuf_size = 0;
  56. if (buf_size == 0)
  57. return 0;
  58. if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
  59. next = buf_size;
  60. } else {
  61. if (!mp->in_sync) {
  62. // Not in sync - find a major sync header
  63. for (i = 0; i < buf_size; i++) {
  64. mp->pc.state = (mp->pc.state << 8) | buf[i];
  65. if ((mp->pc.state & 0xfffffffe) == 0xf8726fba &&
  66. // ignore if we do not have the data for the start of header
  67. mp->pc.index + i >= 7) {
  68. mp->in_sync = 1;
  69. mp->bytes_left = 0;
  70. break;
  71. }
  72. }
  73. if (!mp->in_sync) {
  74. if (ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size) != -1)
  75. av_log(avctx, AV_LOG_WARNING, "ff_combine_frame failed\n");
  76. return buf_size;
  77. }
  78. if ((ret = ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size)) < 0) {
  79. av_log(avctx, AV_LOG_WARNING, "ff_combine_frame failed\n");
  80. return ret;
  81. }
  82. return i - 7;
  83. }
  84. if (mp->bytes_left == 0) {
  85. // Find length of this packet
  86. /* Copy overread bytes from last frame into buffer. */
  87. for(; mp->pc.overread>0; mp->pc.overread--) {
  88. mp->pc.buffer[mp->pc.index++]= mp->pc.buffer[mp->pc.overread_index++];
  89. }
  90. if (mp->pc.index + buf_size < 2) {
  91. if (ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size) != -1)
  92. av_log(avctx, AV_LOG_WARNING, "ff_combine_frame failed\n");
  93. return buf_size;
  94. }
  95. mp->bytes_left = ((mp->pc.index > 0 ? mp->pc.buffer[0] : buf[0]) << 8)
  96. | (mp->pc.index > 1 ? mp->pc.buffer[1] : buf[1-mp->pc.index]);
  97. mp->bytes_left = (mp->bytes_left & 0xfff) * 2;
  98. if (mp->bytes_left <= 0) { // prevent infinite loop
  99. goto lost_sync;
  100. }
  101. mp->bytes_left -= mp->pc.index;
  102. }
  103. next = (mp->bytes_left > buf_size) ? END_NOT_FOUND : mp->bytes_left;
  104. if (ff_combine_frame(&mp->pc, next, &buf, &buf_size) < 0) {
  105. mp->bytes_left -= buf_size;
  106. return buf_size;
  107. }
  108. mp->bytes_left = 0;
  109. }
  110. sync_present = buf_size >= 8 && (AV_RB32(buf + 4) & 0xfffffffe) == 0xf8726fba;
  111. if (!sync_present) {
  112. /* The first nibble of a frame is a parity check of the 4-byte
  113. * access unit header and all the 2- or 4-byte substream headers. */
  114. // Only check when this isn't a sync frame - syncs have a checksum.
  115. s->key_frame = 0;
  116. parity_bits = 0;
  117. for (i = -1; i < mp->num_substreams; i++) {
  118. parity_bits ^= buf[p++];
  119. parity_bits ^= buf[p++];
  120. if (i < 0 || buf[p-2] & 0x80) {
  121. parity_bits ^= buf[p++];
  122. parity_bits ^= buf[p++];
  123. }
  124. }
  125. if ((((parity_bits >> 4) ^ parity_bits) & 0xF) != 0xF) {
  126. av_log(avctx, AV_LOG_INFO, "mlpparse: Parity check failed.\n");
  127. goto lost_sync;
  128. }
  129. } else {
  130. GetBitContext gb;
  131. MLPHeaderInfo mh;
  132. init_get_bits(&gb, buf + 4, (buf_size - 4) << 3);
  133. if (ff_mlp_read_major_sync(avctx, &mh, &gb) < 0)
  134. goto lost_sync;
  135. s->key_frame = 1;
  136. avctx->bits_per_raw_sample = mh.group1_bits;
  137. if (avctx->bits_per_raw_sample > 16)
  138. avctx->sample_fmt = AV_SAMPLE_FMT_S32;
  139. else
  140. avctx->sample_fmt = AV_SAMPLE_FMT_S16;
  141. avctx->sample_rate = mh.group1_samplerate;
  142. avctx->frame_size =
  143. s->duration = mh.access_unit_size;
  144. if(!avctx->channels || !avctx->channel_layout) {
  145. if (mh.stream_type == 0xbb) {
  146. /* MLP stream */
  147. avctx->channels = mh.channels_mlp;
  148. avctx->channel_layout = mh.channel_layout_mlp;
  149. } else { /* mh.stream_type == 0xba */
  150. /* TrueHD stream */
  151. if (!mh.channels_thd_stream2) {
  152. avctx->channels = mh.channels_thd_stream1;
  153. avctx->channel_layout = mh.channel_layout_thd_stream1;
  154. } else {
  155. avctx->channels = mh.channels_thd_stream2;
  156. avctx->channel_layout = mh.channel_layout_thd_stream2;
  157. }
  158. }
  159. }
  160. if (!mh.is_vbr) /* Stream is CBR */
  161. avctx->bit_rate = mh.peak_bitrate;
  162. mp->num_substreams = mh.num_substreams;
  163. }
  164. *poutbuf = buf;
  165. *poutbuf_size = buf_size;
  166. return next;
  167. lost_sync:
  168. mp->in_sync = 0;
  169. return 1;
  170. }
  171. AVCodecParser ff_mlp_parser = {
  172. .codec_ids = { AV_CODEC_ID_MLP, AV_CODEC_ID_TRUEHD },
  173. .priv_data_size = sizeof(MLPParseContext),
  174. .parser_init = mlp_init,
  175. .parser_parse = mlp_parse,
  176. .parser_close = ff_parse_close,
  177. };