summaryrefslogtreecommitdiffstats
path: root/media/mp4/avc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/mp4/avc.cc')
-rw-r--r--media/mp4/avc.cc114
1 files changed, 114 insertions, 0 deletions
diff --git a/media/mp4/avc.cc b/media/mp4/avc.cc
new file mode 100644
index 0000000..faf9939
--- /dev/null
+++ b/media/mp4/avc.cc
@@ -0,0 +1,114 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/mp4/avc.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "media/mp4/box_definitions.h"
+#include "media/mp4/box_reader.h"
+
+namespace media {
+namespace mp4 {
+
+static const uint8 kAnnexBStartCode[] = {0, 0, 0, 1};
+static const int kAnnexBStartCodeSize = 4;
+
+static bool ConvertAVCToAnnexBInPlaceForLengthSize4(std::vector<uint8>* buf) {
+ const int kLengthSize = 4;
+ size_t pos = 0;
+ while (pos + kLengthSize < buf->size()) {
+ int nal_size = (*buf)[pos];
+ nal_size = (nal_size << 8) + (*buf)[pos+1];
+ nal_size = (nal_size << 8) + (*buf)[pos+2];
+ nal_size = (nal_size << 8) + (*buf)[pos+3];
+ std::copy(kAnnexBStartCode, kAnnexBStartCode + kAnnexBStartCodeSize,
+ buf->begin() + pos);
+ pos += kLengthSize + nal_size;
+ }
+ return pos == buf->size();
+}
+
+// static
+bool AVC::ConvertToAnnexB(int length_size, std::vector<uint8>* buffer) {
+ RCHECK(length_size == 1 || length_size == 2 || length_size == 4);
+
+ if (length_size == 4)
+ return ConvertAVCToAnnexBInPlaceForLengthSize4(buffer);
+
+ std::vector<uint8> temp;
+ temp.swap(*buffer);
+ buffer->reserve(temp.size() + 32);
+
+ size_t pos = 0;
+ while (pos + length_size < temp.size()) {
+ int nal_size = temp[pos];
+ if (length_size == 2) nal_size = (nal_size << 8) + temp[pos+1];
+ pos += length_size;
+
+ RCHECK(pos + nal_size <= temp.size());
+ buffer->insert(buffer->end(), kAnnexBStartCode,
+ kAnnexBStartCode + kAnnexBStartCodeSize);
+ buffer->insert(buffer->end(), temp.begin() + pos,
+ temp.begin() + pos + nal_size);
+ pos += nal_size;
+ }
+ return pos == temp.size();
+}
+
+// static
+bool AVC::InsertParameterSets(const AVCDecoderConfigurationRecord& avc_config,
+ std::vector<uint8>* buffer) {
+ int total_size = 0;
+ for (size_t i = 0; i < avc_config.sps_list.size(); i++)
+ total_size += avc_config.sps_list[i].size() + kAnnexBStartCodeSize;
+ for (size_t i = 0; i < avc_config.pps_list.size(); i++)
+ total_size += avc_config.pps_list[i].size() + kAnnexBStartCodeSize;
+
+ std::vector<uint8> temp;
+ temp.reserve(total_size);
+
+ for (size_t i = 0; i < avc_config.sps_list.size(); i++) {
+ temp.insert(temp.end(), kAnnexBStartCode,
+ kAnnexBStartCode + kAnnexBStartCodeSize);
+ temp.insert(temp.end(), avc_config.sps_list[i].begin(),
+ avc_config.sps_list[i].end());
+ }
+
+ for (size_t i = 0; i < avc_config.pps_list.size(); i++) {
+ temp.insert(temp.end(), kAnnexBStartCode,
+ kAnnexBStartCode + kAnnexBStartCodeSize);
+ temp.insert(temp.end(), avc_config.pps_list[i].begin(),
+ avc_config.pps_list[i].end());
+ }
+
+ buffer->insert(buffer->begin(), temp.begin(), temp.end());
+ return true;
+}
+
+// static
+ChannelLayout AVC::ConvertAACChannelCountToChannelLayout(int count) {
+ switch (count) {
+ case 1:
+ return CHANNEL_LAYOUT_MONO;
+ case 2:
+ return CHANNEL_LAYOUT_STEREO;
+ case 3:
+ return CHANNEL_LAYOUT_SURROUND;
+ case 4:
+ return CHANNEL_LAYOUT_4_0;
+ case 5:
+ return CHANNEL_LAYOUT_5_0;
+ case 6:
+ return CHANNEL_LAYOUT_5_1;
+ case 8:
+ return CHANNEL_LAYOUT_7_1;
+ default:
+ return CHANNEL_LAYOUT_UNSUPPORTED;
+ }
+}
+
+} // namespace mp4
+} // namespace media