7 #include <packager/media/base/id3_tag.h>
9 #include <absl/log/log.h>
11 #include <packager/media/base/buffer_writer.h>
12 #include <packager/media/base/fourccs.h>
19 const char kID3v2Identifier[] =
"ID3";
20 const uint16_t kID3v2Version = 0x0400;
22 const uint32_t kMaxSynchsafeSize = 0x0FFFFFFF;
26 uint32_t EncodeSynchsafe(uint32_t size) {
27 return (size & 0x7F) | (((size >> 7) & 0x7F) << 8) |
28 (((size >> 14) & 0x7F) << 16) | (((size >> 21) & 0x7F) << 24);
31 bool WriteId3v2Header(uint32_t frames_size, BufferWriter* buffer_writer) {
32 buffer_writer->AppendString(kID3v2Identifier);
33 buffer_writer->AppendInt(kID3v2Version);
34 const uint8_t flags = 0;
35 buffer_writer->AppendInt(flags);
37 if (frames_size > kMaxSynchsafeSize) {
38 LOG(ERROR) <<
"Input size (" << frames_size
39 <<
") is out of range (> max synchsafe integer "
40 << kMaxSynchsafeSize <<
").";
43 buffer_writer->AppendInt(EncodeSynchsafe(frames_size));
51 const std::string& data) {
52 private_frames_.push_back({owner, data});
57 for (
const PrivateFrame& private_frame : private_frames_) {
58 if (!WritePrivateFrame(private_frame, &frames_buffer))
62 if (!WriteId3v2Header(frames_buffer.Size(), buffer_writer))
64 buffer_writer->AppendBuffer(frames_buffer);
72 buffer_writer.SwapBuffer(output);
77 bool Id3Tag::WritePrivateFrame(
const PrivateFrame& private_frame,
79 buffer_writer->
AppendInt(
static_cast<uint32_t
>(FOURCC_PRIV));
81 const uint32_t frame_size =
static_cast<uint32_t
>(
82 private_frame.owner.size() + 1 + private_frame.data.size());
83 if (frame_size > kMaxSynchsafeSize) {
84 LOG(ERROR) <<
"Input size (" << frame_size
85 <<
") is out of range (> max synchsafe integer "
86 << kMaxSynchsafeSize <<
").";
89 buffer_writer->
AppendInt(EncodeSynchsafe(frame_size));
91 const uint16_t flags = 0;
94 buffer_writer->AppendString(private_frame.owner);
97 buffer_writer->AppendString(private_frame.data);
All the methods that are virtual are virtual for mocking.