Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: media/webm/cluster_builder.cc

Issue 7203002: Adding ChunkDemuxer implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Unit tests and bug fixes Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/webm/cluster_builder.h"
6
7 #include "base/logging.h"
8
9 namespace media {
10
11 static const uint8 kClusterHeader[] = {
12 0x1F, 0x43, 0xB6, 0x75, // CLUSTER ID
scherkus (not reviewing) 2011/06/28 20:03:29 two spaces
acolwell GONE FROM CHROMIUM 2011/06/29 16:38:43 Done.
13 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cluster(size = 0)
14 0xE7, // Timecode ID
15 0x88, // timecode(size=8)
16 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // timecode value
17 };
18
19 const int kClusterHeaderSize = sizeof(kClusterHeader);
20 const int kClusterSizeOffset = 4;
21 const int kClusterTimecodeOffset = 14;
22
23 static const uint8 kSimpleBlockHeader[] = {
24 0xA3, // SimpleBlock ID
scherkus (not reviewing) 2011/06/28 20:03:29 two spaces
acolwell GONE FROM CHROMIUM 2011/06/29 16:38:43 Done.
25 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SimpleBlock(size = 0)
26 };
27
28 const int kSimpleBlockHeaderSize = sizeof(kSimpleBlockHeader);
29 const int kSimpleBlockSizeOffset = 1;
30
31 const int kInitialBufferSize = 32768;
32
33 ClusterBuilder::ClusterBuilder(int64 cluster_timecode)
34 : buffer_(new uint8[kInitialBufferSize]),
35 buffer_size_(kInitialBufferSize),
36 bytes_used_(kClusterHeaderSize),
37 cluster_timecode_(cluster_timecode),
38 finished_(false) {
39 memcpy(buffer_.get(), kClusterHeader, kClusterHeaderSize);
40
41 // Write the timecode into the header.
42 uint8* buf = buffer_.get() + kClusterTimecodeOffset;
43 for (int i = 7; i >= 0; --i) {
44 buf[i] = cluster_timecode & 0xff;
45 cluster_timecode >>= 8;
46 }
47 }
48
49 void ClusterBuilder::AddSimpleBlock(int track_num, int64 timecode, int flags,
50 const uint8* data, int size) {
51 DCHECK_GE(track_num, 0);
52 DCHECK_LE(track_num, 126);
53 DCHECK_GE(flags, 0);
54 DCHECK_LE(flags, 0xff);
55 DCHECK(data);
56 DCHECK_GT(size, 0);
57 DCHECK(!finished_);
58
59 int64 timecode_delta = timecode - cluster_timecode_;
60 DCHECK_GE(timecode_delta, -32768);
61 DCHECK_LE(timecode_delta, 32767);
62
63 int block_size = 4 + size;
64 int bytes_needed = kSimpleBlockHeaderSize + block_size;
65 if (bytes_needed > (buffer_size_ - bytes_used_))
66 ExtendBuffer(bytes_needed);
67
68 uint8* buf = buffer_.get() + bytes_used_;
69 int block_offset = bytes_used_;
70 memcpy(buf, kSimpleBlockHeader, kSimpleBlockHeaderSize);
71 UpdateUInt64(block_offset + kSimpleBlockSizeOffset, block_size);
72 buf += kSimpleBlockHeaderSize;
73
74 buf[0] = 0x80 | (track_num & 0x7F);
75 buf[1] = (timecode_delta >> 8) & 0xff;
76 buf[2] = timecode_delta & 0xff;
77 buf[3] = flags & 0xff;
78 memcpy(buf + 4, data, size);
79
80 bytes_used_ += bytes_needed;
81 }
82
83 void ClusterBuilder::Finish() {
scherkus (not reviewing) 2011/06/28 20:03:29 any checks for calling Finish twice? also what if
acolwell GONE FROM CHROMIUM 2011/06/29 16:38:43 Added a DCHECK, created Cluster object, & updated
84 UpdateUInt64(kClusterSizeOffset, bytes_used_ - (kClusterSizeOffset + 8));
85 finished_ = true;
86 }
87
88 const uint8* ClusterBuilder::GetClusterData() const {
89 DCHECK(finished_) << "Finish() MUST be called before GetClusterData()";
90 return buffer_.get();
91 }
92
93 const int ClusterBuilder::GetClusterDataSize() const {
94 DCHECK(finished_) << "Finish() MUST be called before GetClusterDataSize()";
95 return bytes_used_;
96 }
97
98 void ClusterBuilder::ExtendBuffer(int bytes_needed) {
99 int new_buffer_size = 2 * buffer_size_;
100
101 while ((new_buffer_size - bytes_used_) < bytes_needed)
102 new_buffer_size *= 2;
103
104 scoped_array<uint8> new_buffer(new uint8[new_buffer_size]);
105
106 memcpy(new_buffer.get(), buffer_.get(), bytes_used_);
107 buffer_.reset(new_buffer.release());
108 buffer_size_ = new_buffer_size;
109 }
110
111 void ClusterBuilder::UpdateUInt64(int offset, int64 value) {
112 DCHECK_LE(offset + 7, buffer_size_);
113 uint8* buf = buffer_.get() + offset;
114
115 // Fill the last 7 bytes of size field in big-endian order.
116 for (int i = 7; i > 0; i--) {
117 buf[i] = value & 0xff;
118 value >>= 8;
119 }
120 }
121
122 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698