1 /*
2    mkvmerge -- utility for splicing together matroska files
3    from component media subtypes
4 
5    Distributed under the GPL v2
6    see the file COPYING for details
7    or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
8 
9    definitions and helper functions for AAC data
10 
11    Written by Moritz Bunkus <moritz@bunkus.org>.
12 */
13 
14 #pragma once
15 
16 #include "common/common_pch.h"
17 
18 #include <ostream>
19 
20 #include "common/byte_buffer.h"
21 #include "common/timestamp.h"
22 
23 namespace mtx::bits {
24 class reader_c;
25 class writer_c;
26 }
27 
28 namespace mtx::aac {
29 
30 constexpr auto ID_MPEG4              = 0;
31 constexpr auto ID_MPEG2              = 1;
32 
33 constexpr auto PROFILE_MAIN          = 0;
34 constexpr auto PROFILE_LC            = 1;
35 constexpr auto PROFILE_SSR           = 2;
36 constexpr auto PROFILE_LTP           = 3;
37 constexpr auto PROFILE_SBR           = 4;
38 
39 constexpr auto SYNC_EXTENSION_TYPE   = 0x02b7;
40 
41 constexpr auto MAX_PRIVATE_DATA_SIZE = 5;
42 
43 constexpr auto ADTS_SYNC_WORD        = 0xfff000;
44 constexpr auto ADTS_SYNC_WORD_MASK   = 0xfff000; // first 12 of 24 bits
45 
46 constexpr auto LOAS_SYNC_WORD        = 0x56e000; // 0x2b7
47 constexpr auto LOAS_SYNC_WORD_MASK   = 0xffe000; // first 11 of 24 bits
48 constexpr auto LOAS_FRAME_SIZE_MASK  = 0x001fff; // last 13 of 24 bits
49 
50 constexpr auto ID_PCE                = 0x05; // Table 4.71 "Syntactic elements"
51 
52 struct audio_config_t {
53   unsigned int profile{}, sample_rate{}, output_sample_rate{}, channels{}, samples_per_frame{1024};
54   bool sbr{};
55   memory_cptr ga_specific_config;
56   unsigned int ga_specific_config_bit_size{};
57   bool ga_specific_config_contains_program_config_element{};
58 };
59 
60 unsigned int get_sampling_freq_idx(unsigned int sampling_freq);
61 bool parse_codec_id(const std::string &codec_id, int &id, int &profile);
62 std::optional<audio_config_t> parse_audio_specific_config(unsigned char const *data, std::size_t size);
63 void copy_program_config_element(mtx::bits::reader_c &r, mtx::bits::writer_c &w);
64 memory_cptr create_audio_specific_config(audio_config_t const &audio_config);
65 
66 class header_c {
67 public:
68   audio_config_t config{};
69 
70   unsigned int object_type{}, extension_object_type{}, bit_rate{}, bytes{};
71   unsigned int id{};                       // 0 = MPEG-4, 1 = MPEG-2
72   size_t header_bit_size{}, header_byte_size{}, data_byte_size{};
73 
74   bool is_valid{};
75 
76 protected:
77   mtx::bits::reader_c *m_bc{};
78 
79 public:
80   std::string to_string() const;
81 
82 public:
83   static header_c from_audio_specific_config(const unsigned char *data, size_t size);
84 
85   void parse_audio_specific_config(const unsigned char *data, size_t size, bool look_for_sync_extension = true);
86   void parse_audio_specific_config(mtx::bits::reader_c &bc, bool look_for_sync_extension = true);
87   void parse_program_config_element(mtx::bits::reader_c &bc);
88 
89 protected:
90   int read_object_type();
91   int read_sample_rate();
92   void read_eld_specific_config();
93   void read_er_celp_specific_config();
94   void read_ga_specific_config();
95   void read_program_config_element();
96   void read_error_protection_specific_config();
97 };
98 
99 bool operator ==(const header_c &h1, const header_c &h2);
100 
101 inline std::ostream &
102 operator <<(std::ostream &out,
103             header_c const &header) {
104   out << header.to_string();
105   return out;
106 }
107 
108 class latm_parser_c {
109 protected:
110   int m_audio_mux_version, m_audio_mux_version_a;
111   size_t m_fixed_frame_length, m_frame_length_type, m_frame_bit_offset, m_frame_length;
112   header_c m_header;
113   mtx::bits::reader_c *m_bc;
114   bool m_config_parsed;
115   memory_cptr m_audio_specific_config;
116   debugging_option_c m_debug;
117 
118 public:
119   latm_parser_c();
120 
121   bool config_parsed() const;
122   memory_cptr get_audio_specific_config() const;
123   header_c const &get_header() const;
124   size_t get_frame_bit_offset() const;
125   size_t get_frame_length() const;
126 
127   void parse(mtx::bits::reader_c &bc);
128 
129 protected:
130   unsigned int get_value();
131   void parse_audio_specific_config(size_t asc_length);
132   void parse_stream_mux_config();
133   void parse_payload_mux(size_t length);
134   void parse_audio_mux_element();
135   size_t parse_payload_length_info();
136 };
137 
138 class frame_c {
139 public:
140   header_c m_header;
141   uint64_t m_stream_position;
142   size_t m_garbage_size;
143   timestamp_c m_timestamp;
144   memory_cptr m_data;
145 
146 public:
147   frame_c();
148   void init();
149 
150   std::string to_string(bool verbose = false) const;
151 };
152 
153 class parser_c {
154 public:
155   enum multiplex_type_e {
156       unknown_multiplex = 0
157     , adts_multiplex
158     , adif_multiplex
159     , loas_latm_multiplex
160   };
161 
162 protected:
163   enum parse_result_e {
164       failure
165     , success
166     , need_more_data
167   };
168 
169 protected:
170   std::deque<frame_c> m_frames;
171   std::deque<timestamp_c> m_provided_timestamps;
172   mtx::bytes::buffer_c m_buffer;
173   unsigned char const *m_fixed_buffer;
174   size_t m_fixed_buffer_size;
175   uint64_t m_parsed_stream_position, m_total_stream_position;
176   size_t m_garbage_size, m_num_frames_found, m_abort_after_num_frames;
177   bool m_require_frame_at_first_byte, m_copy_data;
178   multiplex_type_e m_multiplex_type;
179   header_c m_header;
180   latm_parser_c m_latm_parser;
181   debugging_option_c m_debug;
182 
183 public:
184   parser_c();
185   void add_timestamp(timestamp_c const &timestamp);
186 
187   void add_bytes(memory_cptr const &mem);
188   void add_bytes(unsigned char const *buffer, size_t size);
189 
190   void parse_fixed_buffer(unsigned char const *fixed_buffer, size_t fixed_buffer_size);
191   void parse_fixed_buffer(memory_cptr const &fixed_buffer);
192 
193   void flush();
194 
195   multiplex_type_e get_multiplex_type() const;
196   void set_multiplex_type(multiplex_type_e multiplex_type);
197 
198   size_t frames_available() const;
199   bool headers_parsed() const;
200 
201   frame_c get_frame();
202   uint64_t get_parsed_stream_position() const;
203   uint64_t get_total_stream_position() const;
204   memory_cptr get_audio_specific_config() const;
205 
206   void abort_after_num_frames(size_t num_frames);
207   void require_frame_at_first_byte(bool require);
208   void copy_data(bool copy);
209 
210 public:                         // static functions
211   static int find_consecutive_frames(unsigned char const *buffer, size_t buffer_size, size_t num_required_frames);
212   static std::string get_multiplex_type_name(multiplex_type_e multiplex_type);
213 
214 protected:
215   void parse();
216   std::pair<parse_result_e, size_t> decode_header(unsigned char const *buffer, size_t buffer_size);
217   std::pair<parse_result_e, size_t> decode_adts_header(unsigned char const *buffer, size_t buffer_size);
218   std::pair<parse_result_e, size_t> decode_loas_latm_header(unsigned char const *buffer, size_t buffer_size);
219   void push_frame(frame_c &frame);
220 };
221 using parser_cptr = std::shared_ptr<parser_c>;
222 
223 } // namespace mtx::aac
224