1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef FLAC_DEMUXER_H_
8 #define FLAC_DEMUXER_H_
9 
10 #include "mozilla/Attributes.h"
11 #include "MediaDataDemuxer.h"
12 #include "MediaResource.h"
13 namespace mozilla {
14 
15 namespace flac {
16 class Frame;
17 class FrameParser;
18 }  // namespace flac
19 class FlacTrackDemuxer;
20 
21 DDLoggedTypeDeclNameAndBase(FlacDemuxer, MediaDataDemuxer);
22 DDLoggedTypeNameAndBase(FlacTrackDemuxer, MediaTrackDemuxer);
23 
24 class FlacDemuxer : public MediaDataDemuxer,
25                     public DecoderDoctorLifeLogger<FlacDemuxer> {
26  public:
27   // MediaDataDemuxer interface.
28   explicit FlacDemuxer(MediaResource* aSource);
29   RefPtr<InitPromise> Init() override;
30   uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override;
31   already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(
32       TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
33   bool IsSeekable() const override;
34 
35   // Return true if a valid flac frame header could be found.
36   static bool FlacSniffer(const uint8_t* aData, const uint32_t aLength);
37 
38  private:
39   bool InitInternal();
40 
41   RefPtr<MediaResource> mSource;
42   RefPtr<FlacTrackDemuxer> mTrackDemuxer;
43 };
44 
45 class FlacTrackDemuxer : public MediaTrackDemuxer,
46                          public DecoderDoctorLifeLogger<FlacTrackDemuxer> {
47  public:
48   explicit FlacTrackDemuxer(MediaResource* aSource);
49 
50   // Initializes the track demuxer by reading the first frame for meta data.
51   // Returns initialization success state.
52   bool Init();
53 
54   // MediaTrackDemuxer interface.
55   UniquePtr<TrackInfo> GetInfo() const override;
56   RefPtr<SeekPromise> Seek(const media::TimeUnit& aTime) override;
57   RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) override;
58   void Reset() override;
59   int64_t GetResourceOffset() const override;
60   media::TimeIntervals GetBuffered() override;
61   RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(
62       const media::TimeUnit& aTimeThreshold) override;
63 
64   bool IsSeekable() const;
65 
66  private:
67   // Destructor.
68   ~FlacTrackDemuxer();
69 
70   // Returns the estimated stream duration, or a 0-duration if unknown.
71   media::TimeUnit Duration() const;
72   media::TimeUnit TimeAtEnd();
73 
74   // Fast approximate seeking to given time.
75   media::TimeUnit FastSeek(const media::TimeUnit& aTime);
76 
77   // Seeks by scanning the stream up to the given time for more accurate
78   // results.
79   media::TimeUnit ScanUntil(const media::TimeUnit& aTime);
80 
81   // Finds the next valid frame and return it.
82   const flac::Frame& FindNextFrame();
83 
84   // Returns the next ADTS frame, if available.
85   already_AddRefed<MediaRawData> GetNextFrame(const flac::Frame& aFrame);
86 
87   // Reads aSize bytes into aBuffer from the source starting at aOffset.
88   // Returns the actual size read.
89   int32_t Read(uint8_t* aBuffer, int64_t aOffset, int32_t aSize);
90 
91   // Returns the average frame length derived from the previously parsed frames.
92   double AverageFrameLength() const;
93 
94   // The (hopefully) Flac resource.
95   MediaResourceIndex mSource;
96 
97   // Flac frame parser used to detect frames and extract side info.
98   nsAutoPtr<flac::FrameParser> mParser;
99 
100   // Total duration of parsed frames.
101   media::TimeUnit mParsedFramesDuration;
102 
103   // Sum of parsed frames' lengths in bytes.
104   uint64_t mTotalFrameLen;
105 
106   // Audio track config info.
107   UniquePtr<AudioInfo> mInfo;
108 };
109 
110 }  // namespace mozilla
111 
112 #endif  // !FLAC_DEMUXER_H_
113