summaryrefslogtreecommitdiffstats
path: root/dom/media/platforms/android/AndroidDataEncoder.h
blob: ed1dfe770809e06f0b8195cc7c4a20ac531e54a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef DOM_MEDIA_PLATFORMS_ANDROID_ANDROIDDATAENCODER_H_
#define DOM_MEDIA_PLATFORMS_ANDROID_ANDROIDDATAENCODER_H_

#include "MediaData.h"
#include "PlatformEncoderModule.h"

#include "JavaCallbacksSupport.h"

#include "mozilla/Maybe.h"
#include "mozilla/Mutex.h"

namespace mozilla {

class AndroidDataEncoder final : public MediaDataEncoder {
 public:
  AndroidDataEncoder(const EncoderConfig& aConfig,
                     const RefPtr<TaskQueue>& aTaskQueue)
      : mConfig(aConfig), mTaskQueue(aTaskQueue) {
    MOZ_ASSERT(mConfig.mSize.width > 0 && mConfig.mSize.height > 0);
    MOZ_ASSERT(mTaskQueue);
  }
  ~AndroidDataEncoder() { MOZ_ASSERT(!mJavaEncoder); }

  RefPtr<InitPromise> Init() override;
  RefPtr<EncodePromise> Encode(const MediaData* aSample) override;
  RefPtr<EncodePromise> Drain() override;
  RefPtr<ShutdownPromise> Shutdown() override;
  RefPtr<GenericPromise> SetBitrate(uint32_t aBitsPerSec) override;
  RefPtr<ReconfigurationPromise> Reconfigure(
      const RefPtr<const EncoderConfigurationChangeList>& aConfigurationChanges)
      override {
    // General reconfiguration interface not implemented right now
    return MediaDataEncoder::ReconfigurationPromise::CreateAndReject(
        NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
  };

  nsCString GetDescriptionName() const override { return "Android Encoder"_ns; }

 private:
  class CallbacksSupport final : public JavaCallbacksSupport {
   public:
    explicit CallbacksSupport(AndroidDataEncoder* aEncoder)
        : mMutex("AndroidDataEncoder::CallbacksSupport") {
      MutexAutoLock lock(mMutex);
      mEncoder = aEncoder;
    }

    ~CallbacksSupport() {
      MutexAutoLock lock(mMutex);
      mEncoder = nullptr;
    }

    void HandleInput(int64_t aTimestamp, bool aProcessed) override;
    void HandleOutput(java::Sample::Param aSample,
                      java::SampleBuffer::Param aBuffer) override;
    void HandleOutputFormatChanged(
        java::sdk::MediaFormat::Param aFormat) override;
    void HandleError(const MediaResult& aError) override;

   private:
    Mutex mMutex;
    AndroidDataEncoder* mEncoder MOZ_GUARDED_BY(mMutex);
  };
  friend class CallbacksSupport;

  // Methods only called on mTaskQueue.
  RefPtr<InitPromise> ProcessInit();
  RefPtr<EncodePromise> ProcessEncode(const RefPtr<const MediaData>& aSample);
  RefPtr<EncodePromise> ProcessDrain();
  RefPtr<ShutdownPromise> ProcessShutdown();
  void ProcessInput();
  void ProcessOutput(java::Sample::GlobalRef&& aSample,
                     java::SampleBuffer::GlobalRef&& aBuffer);
  RefPtr<MediaRawData> GetOutputData(java::SampleBuffer::Param aBuffer,
                                     const int32_t aOffset, const int32_t aSize,
                                     const bool aIsKeyFrame);
  RefPtr<MediaRawData> GetOutputDataH264(java::SampleBuffer::Param aBuffer,
                                         const int32_t aOffset,
                                         const int32_t aSize,
                                         const bool aIsKeyFrame);
  void Error(const MediaResult& aError);

  void AssertOnTaskQueue() const {
    MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
  }

  EncoderConfig mConfig;

  RefPtr<TaskQueue> mTaskQueue;

  // Can be accessed on any thread, but only written on during init.
  bool mIsHardwareAccelerated = false;

  java::CodecProxy::GlobalRef mJavaEncoder;
  java::CodecProxy::NativeCallbacks::GlobalRef mJavaCallbacks;
  java::sdk::MediaFormat::GlobalRef mFormat;
  // Preallocated Java object used as a reusable storage for input buffer
  // information. Contents must be changed only on mTaskQueue.
  java::sdk::MediaCodec::BufferInfo::GlobalRef mInputBufferInfo;

  MozPromiseHolder<EncodePromise> mDrainPromise;

  // Accessed on mTaskqueue only.
  RefPtr<MediaByteBuffer> mYUVBuffer;
  EncodedData mEncodedData;
  // SPS/PPS NALUs for realtime usage, avcC otherwise.
  RefPtr<MediaByteBuffer> mConfigData;

  enum class DrainState { DRAINABLE, DRAINING, DRAINED };
  DrainState mDrainState = DrainState::DRAINABLE;

  Maybe<MediaResult> mError;
};

}  // namespace mozilla

#endif