7#include <packager/media/base/id3_tag.h>
13#include <absl/log/log.h>
15#include <packager/media/base/buffer_writer.h>
16#include <packager/media/base/fourccs.h>
23const char kID3v2Identifier[] =
"ID3";
24const uint16_t kID3v2Version = 0x0400;
26const uint32_t kMaxSynchsafeSize = 0x0FFFFFFF;
30uint32_t EncodeSynchsafe(uint32_t size) {
31 return (size & 0x7F) | (((size >> 7) & 0x7F) << 8) |
32 (((size >> 14) & 0x7F) << 16) | (((size >> 21) & 0x7F) << 24);
35bool WriteId3v2Header(uint32_t frames_size, BufferWriter* buffer_writer) {
36 buffer_writer->AppendString(kID3v2Identifier);
37 buffer_writer->AppendInt(kID3v2Version);
38 const uint8_t flags = 0;
39 buffer_writer->AppendInt(flags);
41 if (frames_size > kMaxSynchsafeSize) {
42 LOG(ERROR) <<
"Input size (" << frames_size
43 <<
") is out of range (> max synchsafe integer "
44 << kMaxSynchsafeSize <<
").";
47 buffer_writer->AppendInt(EncodeSynchsafe(frames_size));
55 const std::string& data) {
56 private_frames_.push_back({owner, data});
61 for (
const PrivateFrame& private_frame : private_frames_) {
62 if (!WritePrivateFrame(private_frame, &frames_buffer))
66 if (!WriteId3v2Header(frames_buffer.Size(), buffer_writer))
68 buffer_writer->AppendBuffer(frames_buffer);
76 buffer_writer.SwapBuffer(output);
81bool Id3Tag::WritePrivateFrame(
const PrivateFrame& private_frame,
83 buffer_writer->
AppendInt(
static_cast<uint32_t
>(FOURCC_PRIV));
85 const uint32_t frame_size =
static_cast<uint32_t
>(
86 private_frame.owner.size() + 1 + private_frame.data.size());
87 if (frame_size > kMaxSynchsafeSize) {
88 LOG(ERROR) <<
"Input size (" << frame_size
89 <<
") is out of range (> max synchsafe integer "
90 << kMaxSynchsafeSize <<
").";
93 buffer_writer->
AppendInt(EncodeSynchsafe(frame_size));
95 const uint16_t flags = 0;
98 buffer_writer->AppendString(private_frame.owner);
101 buffer_writer->AppendString(private_frame.data);
All the methods that are virtual are virtual for mocking.