tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MP3FrameParser.h (13091B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #ifndef MP3_FRAME_PARSER_H_
      6 #define MP3_FRAME_PARSER_H_
      7 
      8 #include <vector>
      9 
     10 #include "BufferReader.h"
     11 #include "mozilla/Maybe.h"
     12 #include "mozilla/Result.h"
     13 
     14 namespace mozilla {
     15 
     16 // ID3 header parser state machine used by FrameParser.
     17 // The header contains the following format (one byte per term):
     18 // 'I' 'D' '3' MajorVersion MinorVersion Flags Size1 Size2 Size3 Size4
     19 // For more details see https://id3.org/id3v2.4.0-structure
     20 class ID3Parser {
     21 public:
     22  // Holds the ID3 header and its parsing state.
     23  class ID3Header {
     24   public:
     25    // The header size is static, see class comment.
     26    static const int SIZE = 10;
     27    static const int ID3v1_SIZE = 128;
     28 
     29    // Constructor.
     30    ID3Header();
     31 
     32    // Resets the state to allow for a new parsing session.
     33    void Reset();
     34 
     35    // The ID3 tags are versioned like this: ID3vMajorVersion.MinorVersion.
     36    uint8_t MajorVersion() const;
     37    uint8_t MinorVersion() const;
     38 
     39    // The ID3 flags field.
     40    uint8_t Flags() const;
     41 
     42    // The derived size based on the provided size fields.
     43    uint32_t Size() const;
     44 
     45    // To see whether we have parsed the value of the size from header.
     46    bool HasSizeBeenSet() const;
     47 
     48    // Returns the size of an ID3v2.4 footer if present and zero otherwise.
     49    uint8_t FooterSize() const;
     50 
     51    // The total size of the ID3 tag including header/footer, or zero if
     52    // none has been found.
     53    uint32_t TotalTagSize() const;
     54 
     55    // Returns whether the parsed data is a valid ID3 header up to the given
     56    // byte position.
     57    bool IsValid(int aPos) const;
     58 
     59    // Returns whether the parsed data is a complete and valid ID3 header.
     60    bool IsValid() const;
     61 
     62    // Parses the next provided byte.
     63    // Returns whether the byte creates a valid sequence up to this point.
     64    bool ParseNext(uint8_t c);
     65 
     66   private:
     67    // Updates the parser state machine with the provided next byte.
     68    // Returns whether the provided byte is a valid next byte in the sequence.
     69    bool Update(uint8_t c);
     70 
     71    // The currently parsed byte sequence.
     72    uint8_t mRaw[SIZE] = {};
     73 
     74    // The derived size as provided by the size fields.
     75    // The header size fields holds a 4 byte sequence with each MSB set to 0,
     76    // this bits need to be ignored when deriving the actual size.
     77    Maybe<uint32_t> mSize;
     78 
     79    // The current byte position in the parsed sequence. Reset via Reset and
     80    // incremented via Update.
     81    int mPos = 0;
     82  };
     83 
     84  // Check if the buffer is starting with ID3v2 tag.
     85  static bool IsBufferStartingWithID3Tag(BufferReader* aReader);
     86  // Similarly, if the buffer is starting with ID3v1 tag.
     87  static bool IsBufferStartingWithID3v1Tag(BufferReader* aReader);
     88 
     89  // Returns the parsed ID3 header. Note: check for validity.
     90  const ID3Header& Header() const;
     91 
     92  // Returns the size of all parsed ID3 headers.
     93  uint32_t TotalHeadersSize() const;
     94 
     95  // Parses contents of given BufferReader for a valid ID3v2 header.
     96  // Returns the parsed ID3v2 tag size if successful and zero otherwise.
     97  uint32_t Parse(BufferReader* aReader);
     98 
     99  // Resets the state to allow for a new parsing session.
    100  void Reset();
    101 
    102 private:
    103  uint32_t ParseInternal(BufferReader* aReader);
    104 
    105  // The currently parsed ID3 header. Reset via Reset, updated via Parse.
    106  ID3Header mHeader;
    107  // If a file contains multiple ID3 headers, then we would only select the
    108  // latest one, but keep the size of former abandoned in order to return the
    109  // correct size offset.
    110  uint32_t mFormerID3Size = 0;
    111 };
    112 
    113 // MPEG audio frame parser.
    114 // The MPEG frame header has the following format (one bit per character):
    115 // 11111111 111VVLLC BBBBSSPR MMEETOHH
    116 // {   sync   } - 11 sync bits
    117 //   VV         - MPEG audio version ID (0->2.5, 1->reserved, 2->2, 3->1)
    118 //   LL         - Layer description (0->reserved, 1->III, 2->II, 3->I)
    119 //   C          - CRC protection bit (0->protected, 1->not protected)
    120 //   BBBB       - Bitrate index (see table in implementation)
    121 //   SS         - Sampling rate index (see table in implementation)
    122 //   P          - Padding bit (0->not padded, 1->padded by 1 slot size)
    123 //   R          - Private bit (ignored)
    124 //   MM         - Channel mode (0->stereo, 1->joint stereo, 2->dual channel,
    125 //                3->single channel)
    126 //   EE         - Mode extension for joint stereo (ignored)
    127 //   T          - Copyright (0->disabled, 1->enabled)
    128 //   O          - Original (0->copy, 1->original)
    129 //   HH         - Emphasis (0->none, 1->50/15 ms, 2->reserved, 3->CCIT J.17)
    130 class FrameParser {
    131 public:
    132  // Holds the frame header and its parsing state.
    133  class FrameHeader {
    134   public:
    135    // The header size is static, see class comments.
    136    static const int SIZE = 4;
    137 
    138    // Constructor.
    139    FrameHeader();
    140 
    141    // Raw field access, see class comments for details.
    142    uint8_t Sync1() const;
    143    uint8_t Sync2() const;
    144    uint8_t RawVersion() const;
    145    uint8_t RawLayer() const;
    146    uint8_t RawProtection() const;
    147    uint8_t RawBitrate() const;
    148    uint8_t RawSampleRate() const;
    149    uint8_t Padding() const;
    150    uint8_t Private() const;
    151    uint8_t RawChannelMode() const;
    152 
    153    // Sampling rate frequency in Hz.
    154    uint32_t SampleRate() const;
    155 
    156    // Number of audio channels.
    157    uint32_t Channels() const;
    158 
    159    // Samples per frames, static depending on MPEG version and layer.
    160    uint32_t SamplesPerFrame() const;
    161 
    162    // Slot size used for padding, static depending on MPEG layer.
    163    uint32_t SlotSize() const;
    164 
    165    // Bitrate in kbps, can vary between frames.
    166    uint32_t Bitrate() const;
    167 
    168    // MPEG layer (0->invalid, 1->I, 2->II, 3->III).
    169    uint32_t Layer() const;
    170 
    171    // Returns whether the parsed data is a valid frame header up to the given
    172    // byte position.
    173    bool IsValid(const int aPos) const;
    174 
    175    // Returns whether the parsed data is a complete and valid frame header.
    176    bool IsValid() const;
    177 
    178    // Resets the state to allow for a new parsing session.
    179    void Reset();
    180 
    181    // Parses the next provided byte.
    182    // Returns whether the byte creates a valid sequence up to this point.
    183    bool ParseNext(const uint8_t c);
    184 
    185   private:
    186    // Updates the parser state machine with the provided next byte.
    187    // Returns whether the provided byte is a valid next byte in the sequence.
    188    bool Update(const uint8_t c);
    189 
    190    // The currently parsed byte sequence.
    191    uint8_t mRaw[SIZE] = {};
    192 
    193    // The current byte position in the parsed sequence. Reset via Reset and
    194    // incremented via Update.
    195    int mPos = 0;
    196  };
    197 
    198  // VBR frames may contain Xing or VBRI headers for additional info, we use
    199  // this class to parse them and access this info.
    200  class VBRHeader {
    201   public:
    202    // Synchronize with vbr_header TYPE_STR on change.
    203    enum VBRHeaderType { NONE = 0, XING, VBRI };
    204 
    205    // Constructor.
    206    VBRHeader();
    207 
    208    // Returns the parsed VBR header type, or NONE if no valid header found.
    209    VBRHeaderType Type() const;
    210 
    211    // Returns the total number of audio frames (excluding the VBR header frame)
    212    // expected in the stream/file.
    213    const Maybe<uint32_t>& NumAudioFrames() const;
    214 
    215    // Returns the expected size of the stream.
    216    const Maybe<uint32_t>& NumBytes() const;
    217 
    218    // Returns the VBR scale factor (0: best quality, 100: lowest quality).
    219    const Maybe<uint32_t>& Scale() const;
    220 
    221    // Returns true iff Xing/Info TOC (table of contents) is present.
    222    bool IsTOCPresent() const;
    223 
    224    // Returns whether the header is valid (type XING or VBRI).
    225    bool IsValid() const;
    226 
    227    // Returns whether the header is valid and contains reasonable non-zero
    228    // field values.
    229    bool IsComplete() const;
    230 
    231    // Returns the byte offset for the given duration percentage as a factor
    232    // (0: begin, 1.0: end).
    233    int64_t Offset(media::TimeUnit aTime, media::TimeUnit aDuration) const;
    234 
    235    // Parses contents of given ByteReader for a valid VBR header.
    236    // The offset of the passed ByteReader needs to point to an MPEG frame
    237    // begin, as a VBRI-style header is searched at a fixed offset relative to
    238    // frame begin. Returns whether a valid VBR header was found in the range.
    239    bool Parse(BufferReader* aReader, size_t aFrameSize);
    240 
    241    uint32_t EncoderDelay() const { return mEncoderDelay; }
    242    uint32_t EncoderPadding() const { return mEncoderPadding; }
    243 
    244   private:
    245    // Parses contents of given ByteReader for a valid Xing header.
    246    // The initial ByteReader offset will be preserved.
    247    // Returns whether a valid Xing header was found in the range.
    248    Result<bool, nsresult> ParseXing(BufferReader* aReader, size_t aFrameSize);
    249 
    250    // Parses contents of given ByteReader for a valid VBRI header.
    251    // The initial ByteReader offset will be preserved. It also needs to point
    252    // to the beginning of a valid MPEG frame, as VBRI headers are searched
    253    // at a fixed offset relative to frame begin.
    254    // Returns whether a valid VBRI header was found in the range.
    255    Result<bool, nsresult> ParseVBRI(BufferReader* aReader);
    256 
    257    // The total number of frames expected as parsed from a VBR header.
    258    Maybe<uint32_t> mNumAudioFrames;
    259 
    260    // The total number of bytes expected in the stream.
    261    Maybe<uint32_t> mNumBytes;
    262 
    263    // The VBR scale factor.
    264    Maybe<uint32_t> mScale;
    265 
    266    // The TOC table mapping duration percentage to byte offset.
    267    std::vector<int64_t> mTOC;
    268 
    269    // The detected VBR header type.
    270    VBRHeaderType mType;
    271 
    272    uint16_t mVBRISeekOffsetsFramesPerEntry = 0;
    273 
    274    // Delay and padding values found in the LAME header. The encoder delay is a
    275    // number of frames that has to be skipped at the beginning of the stream,
    276    // encoder padding is a number of frames that needs to be ignored in the
    277    // last packet.
    278    uint16_t mEncoderDelay = 0;
    279    uint16_t mEncoderPadding = 0;
    280  };
    281 
    282  // Frame meta container used to parse and hold a frame header and side info.
    283  class Frame {
    284   public:
    285    // Returns the length of the frame excluding the header in bytes.
    286    uint32_t Length() const;
    287 
    288    // Returns the parsed frame header.
    289    const FrameHeader& Header() const;
    290 
    291    // Resets the frame header and data.
    292    void Reset();
    293 
    294    // Parses the next provided byte.
    295    // Returns whether the byte creates a valid sequence up to this point.
    296    bool ParseNext(uint8_t c);
    297 
    298   private:
    299    // The currently parsed frame header.
    300    FrameHeader mHeader;
    301  };
    302 
    303  // Constructor.
    304  FrameParser();
    305 
    306  // Returns the currently parsed frame. Reset via Reset or EndFrameSession.
    307  const Frame& CurrentFrame() const;
    308 
    309  // Returns the previously parsed frame. Reset via Reset.
    310  const Frame& PrevFrame() const;
    311 
    312  // Returns the first parsed frame. Reset via Reset.
    313  const Frame& FirstFrame() const;
    314 
    315  // Returns the parsed ID3 header. Note: check for validity.
    316  const ID3Parser::ID3Header& ID3Header() const;
    317 
    318  // Returns whether ID3 metadata have been found, at the end of the file.
    319  bool ID3v1MetadataFound() const;
    320 
    321  // Returns the size of all parsed ID3 headers.
    322  uint32_t TotalID3HeaderSize() const;
    323 
    324  // Returns the parsed VBR header info. Note: check for validity by type.
    325  const VBRHeader& VBRInfo() const;
    326 
    327  // Resets the parser.
    328  void Reset();
    329 
    330  // Resets all frame data, but not the ID3Header.
    331  // Don't use between frames as first frame data is reset.
    332  void ResetFrameData();
    333 
    334  // Clear the last parsed frame to allow for next frame parsing, i.e.:
    335  // - sets PrevFrame to CurrentFrame
    336  // - resets the CurrentFrame
    337  // - resets ID3Header if no valid header was parsed yet
    338  void EndFrameSession();
    339 
    340  // Parses contents of given BufferReader for a valid frame header and returns
    341  // true if one was found. After returning, the variable passed to
    342  // 'aBytesToSkip' holds the amount of bytes to be skipped (if any) in order to
    343  // jump across a large ID3v2 tag spanning multiple buffers.
    344  Result<bool, nsresult> Parse(BufferReader* aReader, uint32_t* aBytesToSkip);
    345 
    346  // Parses contents of given BufferReader for a valid VBR header.
    347  // The offset of the passed BufferReader needs to point to an MPEG frame
    348  // begin, as a VBRI-style header is searched at a fixed offset relative to
    349  // frame begin. Returns whether a valid VBR header was found.
    350  bool ParseVBRHeader(BufferReader* aReader);
    351 
    352 private:
    353  // ID3 header parser.
    354  ID3Parser mID3Parser;
    355 
    356  // VBR header parser.
    357  VBRHeader mVBRHeader;
    358 
    359  // We keep the first parsed frame around for static info access, the
    360  // previously parsed frame for debugging and the currently parsed frame.
    361  Frame mFirstFrame;
    362  Frame mFrame;
    363  Frame mPrevFrame;
    364  // If this is true, ID3v1 metadata have been found at the end of the file, and
    365  // must be sustracted from the stream size in order to compute the stream
    366  // duration, when computing the duration of a CBR file based on its length in
    367  // bytes. This means that the duration can change at the moment we reach the
    368  // end of the file.
    369  bool mID3v1MetadataFound = false;
    370 };
    371 
    372 }  // namespace mozilla
    373 
    374 #endif