Bug 1161276: part 2 - pass bitrates to track encoders for MediaRecorder r=roc

This commit is contained in:
Maire Reavy 2015-06-08 11:47:28 +08:00
Родитель 5e7ac88cc7
Коммит 1939f24ed7
8 изменённых файлов: 70 добавлений и 8 удалений

Просмотреть файл

@ -595,9 +595,17 @@ private:
// Make sure the application has permission to assign AUDIO_3GPP // Make sure the application has permission to assign AUDIO_3GPP
if (mRecorder->mMimeType.EqualsLiteral(AUDIO_3GPP) && Check3gppPermission()) { if (mRecorder->mMimeType.EqualsLiteral(AUDIO_3GPP) && Check3gppPermission()) {
mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(AUDIO_3GPP), aTrackTypes); mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(AUDIO_3GPP),
mRecorder->GetAudioBitrate(),
mRecorder->GetVideoBitrate(),
mRecorder->GetBitrate(),
aTrackTypes);
} else { } else {
mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(""), aTrackTypes); mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(""),
mRecorder->GetAudioBitrate(),
mRecorder->GetVideoBitrate(),
mRecorder->GetBitrate(),
aTrackTypes);
} }
if (!mEncoder) { if (!mEncoder) {
@ -1015,6 +1023,17 @@ MediaRecorder::SetOptions(const MediaRecorderOptions& aInitDict)
aInitDict.mVideoBitsPerSecond.Value() : 0; aInitDict.mVideoBitsPerSecond.Value() : 0;
mBitsPerSecond = aInitDict.mBitsPerSecond.WasPassed() ? mBitsPerSecond = aInitDict.mBitsPerSecond.WasPassed() ?
aInitDict.mBitsPerSecond.Value() : 0; aInitDict.mBitsPerSecond.Value() : 0;
// We're not handling dynamic changes yet. Eventually we'll handle
// setting audio, video and/or total -- and anything that isn't set,
// we'll derive. Calculated versions require querying bitrates after
// the encoder is Init()ed. This happens only after data is
// available and thus requires dynamic changes.
//
// Until dynamic changes are supported, I prefer to be safe and err
// slightly high
if (aInitDict.mBitsPerSecond.WasPassed() && !aInitDict.mVideoBitsPerSecond.WasPassed()) {
mVideoBitsPerSecond = mBitsPerSecond;
}
} }
nsresult nsresult

Просмотреть файл

@ -104,6 +104,9 @@ public:
NS_DECL_NSIDOCUMENTACTIVITY NS_DECL_NSIDOCUMENTACTIVITY
uint32_t GetAudioBitrate() { return mAudioBitsPerSecond; }
uint32_t GetVideoBitrate() { return mVideoBitsPerSecond; }
uint32_t GetBitrate() { return mBitsPerSecond; }
protected: protected:
virtual ~MediaRecorder(); virtual ~MediaRecorder();

Просмотреть файл

@ -73,7 +73,9 @@ MediaEncoder::NotifyEvent(MediaStreamGraph* aGraph,
/* static */ /* static */
already_AddRefed<MediaEncoder> already_AddRefed<MediaEncoder>
MediaEncoder::CreateEncoder(const nsAString& aMIMEType, uint8_t aTrackTypes) MediaEncoder::CreateEncoder(const nsAString& aMIMEType, uint32_t aAudioBitrate,
uint32_t aVideoBitrate, uint32_t aBitrate,
uint8_t aTrackTypes)
{ {
if (!gMediaEncoderLog) { if (!gMediaEncoderLog) {
gMediaEncoderLog = PR_NewLogModule("MediaEncoder"); gMediaEncoderLog = PR_NewLogModule("MediaEncoder");
@ -144,8 +146,15 @@ MediaEncoder::CreateEncoder(const nsAString& aMIMEType, uint8_t aTrackTypes)
LOG(LogLevel::Debug, ("Create encoder result:a[%d] v[%d] w[%d] mimeType = %s.", LOG(LogLevel::Debug, ("Create encoder result:a[%d] v[%d] w[%d] mimeType = %s.",
audioEncoder != nullptr, videoEncoder != nullptr, audioEncoder != nullptr, videoEncoder != nullptr,
writer != nullptr, mimeType.get())); writer != nullptr, mimeType.get()));
if (videoEncoder && aVideoBitrate != 0) {
videoEncoder->SetBitrate(aVideoBitrate);
}
if (audioEncoder && aAudioBitrate != 0) {
audioEncoder->SetBitrate(aAudioBitrate);
}
encoder = new MediaEncoder(writer.forget(), audioEncoder.forget(), encoder = new MediaEncoder(writer.forget(), audioEncoder.forget(),
videoEncoder.forget(), mimeType); videoEncoder.forget(), mimeType, aAudioBitrate,
aVideoBitrate, aBitrate);
return encoder.forget(); return encoder.forget();
} }

Просмотреть файл

@ -62,7 +62,10 @@ public :
MediaEncoder(ContainerWriter* aWriter, MediaEncoder(ContainerWriter* aWriter,
AudioTrackEncoder* aAudioEncoder, AudioTrackEncoder* aAudioEncoder,
VideoTrackEncoder* aVideoEncoder, VideoTrackEncoder* aVideoEncoder,
const nsAString& aMIMEType) const nsAString& aMIMEType,
uint32_t aAudioBitrate,
uint32_t aVideoBitrate,
uint32_t aBitrate)
: mWriter(aWriter) : mWriter(aWriter)
, mAudioEncoder(aAudioEncoder) , mAudioEncoder(aAudioEncoder)
, mVideoEncoder(aVideoEncoder) , mVideoEncoder(aVideoEncoder)
@ -96,6 +99,8 @@ public :
* Ogg+Opus if it is empty. * Ogg+Opus if it is empty.
*/ */
static already_AddRefed<MediaEncoder> CreateEncoder(const nsAString& aMIMEType, static already_AddRefed<MediaEncoder> CreateEncoder(const nsAString& aMIMEType,
uint32_t aAudioBitrate, uint32_t aVideoBitrate,
uint32_t aBitrate,
uint8_t aTrackTypes = ContainerWriter::CREATE_AUDIO_TRACK); uint8_t aTrackTypes = ContainerWriter::CREATE_AUDIO_TRACK);
/** /**
* Encodes the raw track data and returns the final container data. Assuming * Encodes the raw track data and returns the final container data. Assuming

Просмотреть файл

@ -187,8 +187,13 @@ OpusTrackEncoder::Init(int aChannels, int aSamplingRate)
mEncoder = opus_encoder_create(GetOutputSampleRate(), mChannels, mEncoder = opus_encoder_create(GetOutputSampleRate(), mChannels,
OPUS_APPLICATION_AUDIO, &error); OPUS_APPLICATION_AUDIO, &error);
mInitialized = (error == OPUS_OK); mInitialized = (error == OPUS_OK);
if (mAudioBitrate) {
opus_encoder_ctl(mEncoder, OPUS_SET_BITRATE(static_cast<int>(mAudioBitrate)));
}
mReentrantMonitor.NotifyAll(); mReentrantMonitor.NotifyAll();
return error == OPUS_OK ? NS_OK : NS_ERROR_FAILURE; return error == OPUS_OK ? NS_OK : NS_ERROR_FAILURE;

Просмотреть файл

@ -84,6 +84,8 @@ public:
mReentrantMonitor.NotifyAll(); mReentrantMonitor.NotifyAll();
} }
virtual void SetBitrate(const uint32_t aBitrate) {}
protected: protected:
/** /**
* Notifies track encoder that we have reached the end of source stream, and * Notifies track encoder that we have reached the end of source stream, and
@ -141,6 +143,7 @@ public:
: TrackEncoder() : TrackEncoder()
, mChannels(0) , mChannels(0)
, mSamplingRate(0) , mSamplingRate(0)
, mAudioBitrate(0)
{} {}
virtual void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID, virtual void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
@ -191,6 +194,10 @@ public:
*/ */
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
virtual void SetBitrate(const uint32_t aBitrate) override
{
mAudioBitrate = aBitrate;
}
protected: protected:
/** /**
* Number of samples per channel in a pcm buffer. This is also the value of * Number of samples per channel in a pcm buffer. This is also the value of
@ -239,6 +246,8 @@ protected:
* A segment queue of audio track data, protected by mReentrantMonitor. * A segment queue of audio track data, protected by mReentrantMonitor.
*/ */
AudioSegment mRawSegment; AudioSegment mRawSegment;
uint32_t mAudioBitrate;
}; };
class VideoTrackEncoder : public TrackEncoder class VideoTrackEncoder : public TrackEncoder
@ -252,6 +261,7 @@ public:
, mDisplayHeight(0) , mDisplayHeight(0)
, mTrackRate(0) , mTrackRate(0)
, mTotalFrameDuration(0) , mTotalFrameDuration(0)
, mVideoBitrate(0)
{} {}
/** /**
@ -267,6 +277,10 @@ public:
*/ */
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
virtual void SetBitrate(const uint32_t aBitrate) override
{
mVideoBitrate = aBitrate;
}
protected: protected:
/** /**
* Initialized the video encoder. In order to collect the value of width and * Initialized the video encoder. In order to collect the value of width and
@ -332,6 +346,8 @@ protected:
* A segment queue of audio track data, protected by mReentrantMonitor. * A segment queue of audio track data, protected by mReentrantMonitor.
*/ */
VideoSegment mRawSegment; VideoSegment mRawSegment;
uint32_t mVideoBitrate;
}; };
} // namespace mozilla } // namespace mozilla

Просмотреть файл

@ -20,7 +20,7 @@ PRLogModuleInfo* gVP8TrackEncoderLog;
(msg, ##__VA_ARGS__)) (msg, ##__VA_ARGS__))
// Debug logging macro with object pointer and class name. // Debug logging macro with object pointer and class name.
#define DEFAULT_BITRATE 2500 // in kbit/s #define DEFAULT_BITRATE_BPS 2500000
#define DEFAULT_ENCODE_FRAMERATE 30 #define DEFAULT_ENCODE_FRAMERATE 30
using namespace mozilla::layers; using namespace mozilla::layers;
@ -87,7 +87,9 @@ VP8TrackEncoder::Init(int32_t aWidth, int32_t aHeight, int32_t aDisplayWidth,
config.g_h = mFrameHeight; config.g_h = mFrameHeight;
// TODO: Maybe we should have various aFrameRate bitrate pair for each devices? // TODO: Maybe we should have various aFrameRate bitrate pair for each devices?
// or for different platform // or for different platform
config.rc_target_bitrate = DEFAULT_BITRATE; // in kbit/s
// rc_target_bitrate needs kbit/s
config.rc_target_bitrate = (mVideoBitrate != 0 ? mVideoBitrate : DEFAULT_BITRATE_BPS)/1000;
// Setting the time base of the codec // Setting the time base of the codec
config.g_timebase.num = 1; config.g_timebase.num = 1;

Просмотреть файл

@ -56,9 +56,12 @@ VorbisTrackEncoder::Init(int aChannels, int aSamplingRate)
int ret = 0; int ret = 0;
vorbis_info_init(&mVorbisInfo); vorbis_info_init(&mVorbisInfo);
double quality = mAudioBitrate ? (double)mAudioBitrate/aSamplingRate :
BASE_QUALITY;
printf("quality %f \n", quality);
ret = vorbis_encode_init_vbr(&mVorbisInfo, mChannels, mSamplingRate, ret = vorbis_encode_init_vbr(&mVorbisInfo, mChannels, mSamplingRate,
BASE_QUALITY); quality);
mInitialized = (ret == 0); mInitialized = (ret == 0);