1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "WebMWriter.h"
7 #include "EbmlComposer.h"
8 #include "GeckoProfiler.h"
9 #include "OpusTrackEncoder.h"
10
11 namespace mozilla {
12
WebMWriter()13 WebMWriter::WebMWriter()
14 : ContainerWriter(), mEbmlComposer(new EbmlComposer()) {}
15
~WebMWriter()16 WebMWriter::~WebMWriter() {
17 // Out-of-line dtor so mEbmlComposer UniquePtr can delete a complete type.
18 }
19
WriteEncodedTrack(const nsTArray<RefPtr<EncodedFrame>> & aData,uint32_t aFlags)20 nsresult WebMWriter::WriteEncodedTrack(
21 const nsTArray<RefPtr<EncodedFrame>>& aData, uint32_t aFlags) {
22 AUTO_PROFILER_LABEL("WebMWriter::WriteEncodedTrack", OTHER);
23 for (uint32_t i = 0; i < aData.Length(); i++) {
24 mEbmlComposer->WriteSimpleBlock(aData.ElementAt(i).get());
25 }
26 return NS_OK;
27 }
28
GetContainerData(nsTArray<nsTArray<uint8_t>> * aOutputBufs,uint32_t aFlags)29 nsresult WebMWriter::GetContainerData(nsTArray<nsTArray<uint8_t>>* aOutputBufs,
30 uint32_t aFlags) {
31 AUTO_PROFILER_LABEL("WebMWriter::GetContainerData", OTHER);
32 mEbmlComposer->ExtractBuffer(aOutputBufs, aFlags);
33 if (aFlags & ContainerWriter::FLUSH_NEEDED) {
34 mIsWritingComplete = true;
35 }
36 return NS_OK;
37 }
38
SetMetadata(const nsTArray<RefPtr<TrackMetadataBase>> & aMetadata)39 nsresult WebMWriter::SetMetadata(
40 const nsTArray<RefPtr<TrackMetadataBase>>& aMetadata) {
41 AUTO_PROFILER_LABEL("WebMWriter::SetMetadata", OTHER);
42 MOZ_DIAGNOSTIC_ASSERT(!aMetadata.IsEmpty());
43
44 // Integrity checks
45 bool bad = false;
46 for (const RefPtr<TrackMetadataBase>& metadata : aMetadata) {
47 MOZ_ASSERT(metadata);
48
49 if (metadata->GetKind() == TrackMetadataBase::METADATA_VP8) {
50 VP8Metadata* meta = static_cast<VP8Metadata*>(metadata.get());
51 if (meta->mWidth == 0 || meta->mHeight == 0 || meta->mDisplayWidth == 0 ||
52 meta->mDisplayHeight == 0) {
53 bad = true;
54 }
55 }
56
57 if (metadata->GetKind() == TrackMetadataBase::METADATA_VORBIS) {
58 VorbisMetadata* meta = static_cast<VorbisMetadata*>(metadata.get());
59 if (meta->mSamplingFrequency == 0 || meta->mChannels == 0 ||
60 meta->mData.IsEmpty()) {
61 bad = true;
62 }
63 }
64
65 if (metadata->GetKind() == TrackMetadataBase::METADATA_OPUS) {
66 OpusMetadata* meta = static_cast<OpusMetadata*>(metadata.get());
67 if (meta->mSamplingFrequency == 0 || meta->mChannels == 0 ||
68 meta->mIdHeader.IsEmpty()) {
69 bad = true;
70 }
71 }
72 }
73 if (bad) {
74 return NS_ERROR_FAILURE;
75 }
76
77 // Storing
78 DebugOnly<bool> hasAudio = false;
79 DebugOnly<bool> hasVideo = false;
80 for (const RefPtr<TrackMetadataBase>& metadata : aMetadata) {
81 MOZ_ASSERT(metadata);
82
83 if (metadata->GetKind() == TrackMetadataBase::METADATA_VP8) {
84 MOZ_ASSERT(!hasVideo);
85 VP8Metadata* meta = static_cast<VP8Metadata*>(metadata.get());
86 mEbmlComposer->SetVideoConfig(meta->mWidth, meta->mHeight,
87 meta->mDisplayWidth, meta->mDisplayHeight);
88 hasVideo = true;
89 }
90
91 if (metadata->GetKind() == TrackMetadataBase::METADATA_VORBIS) {
92 MOZ_ASSERT(!hasAudio);
93 VorbisMetadata* meta = static_cast<VorbisMetadata*>(metadata.get());
94 mEbmlComposer->SetAudioConfig(meta->mSamplingFrequency, meta->mChannels);
95 mEbmlComposer->SetAudioCodecPrivateData(meta->mData);
96 hasAudio = true;
97 }
98
99 if (metadata->GetKind() == TrackMetadataBase::METADATA_OPUS) {
100 MOZ_ASSERT(!hasAudio);
101 OpusMetadata* meta = static_cast<OpusMetadata*>(metadata.get());
102 mEbmlComposer->SetAudioConfig(meta->mSamplingFrequency, meta->mChannels);
103 mEbmlComposer->SetAudioCodecPrivateData(meta->mIdHeader);
104 hasAudio = true;
105 }
106 }
107 mEbmlComposer->GenerateHeader();
108 return NS_OK;
109 }
110
111 } // namespace mozilla
112