• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 3-Clause Clear License
5  * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6  * License was not distributed with this source code in the LICENSE file, you
7  * can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
8  * Alliance for Open Media Patent License 1.0 was not distributed with this
9  * source code in the PATENTS file, you can obtain it at
10  * www.aomedia.org/license/patent.
11  */
12 
13 #include "iamf/obu/obu_base.h"
14 
15 #include <cstdint>
16 #include <memory>
17 
18 #include "absl/status/status.h"
19 #include "absl/strings/str_cat.h"
20 #include "absl/types/span.h"
21 #include "iamf/common/leb_generator.h"
22 #include "iamf/common/read_bit_buffer.h"
23 #include "iamf/common/utils/macros.h"
24 #include "iamf/common/write_bit_buffer.h"
25 #include "iamf/obu/obu_header.h"
26 
27 namespace iamf_tools {
28 
~ObuBase()29 ObuBase::~ObuBase() {}
30 
ValidateAndWriteObu(WriteBitBuffer & final_wb) const31 absl::Status ObuBase::ValidateAndWriteObu(WriteBitBuffer& final_wb) const {
32   // Allocate a temporary buffer big enough for most OBUs to assist writing, but
33   // make it resizable so it can be expanded for large OBUs.
34   static const int64_t kBufferSize = 1024;
35   WriteBitBuffer temp_wb(kBufferSize, final_wb.leb_generator_);
36 
37   // Write the payload to a temporary buffer using the virtual function.
38   RETURN_IF_NOT_OK(ValidateAndWritePayload(temp_wb));
39   // Write the footer to the temporary buffer.
40   RETURN_IF_NOT_OK(temp_wb.WriteUint8Span(absl::MakeConstSpan(footer_)));
41   if (!temp_wb.IsByteAligned()) {
42     // The header stores the size of the OBU in bytes.
43     return absl::InvalidArgumentError(absl::StrCat(
44         "Expected the OBU payload to be byte-aligned: ", temp_wb.bit_offset()));
45   }
46 
47   // Write the header now that the payload size is known.
48   const int64_t payload_size_bytes = temp_wb.bit_buffer().size();
49 
50   RETURN_IF_NOT_OK(header_.ValidateAndWrite(payload_size_bytes, final_wb));
51 
52   const int64_t expected_end_payload =
53       final_wb.bit_offset() + payload_size_bytes * 8;
54 
55   // Copy over the payload into the final write buffer.
56   RETURN_IF_NOT_OK(
57       final_wb.WriteUint8Span(absl::MakeConstSpan(temp_wb.bit_buffer())));
58 
59   // Validate the write buffer is at the expected location expected after
60   // writing the payload.
61   if (expected_end_payload != final_wb.bit_offset()) {
62     return absl::InvalidArgumentError(absl::StrCat(
63         "Expected end_payload: ", expected_end_payload,
64         " to be equal to write buffer bit offset: ", final_wb.bit_offset()));
65   }
66 
67   return absl::OkStatus();
68 }
69 
ReadAndValidatePayload(int64_t payload_size_bytes,ReadBitBuffer & rb)70 absl::Status ObuBase::ReadAndValidatePayload(int64_t payload_size_bytes,
71                                              ReadBitBuffer& rb) {
72   const int64_t expected_final_position = rb.Tell() + (payload_size_bytes * 8);
73 
74   // Read the known portion of the payload.
75   RETURN_IF_NOT_OK(ReadAndValidatePayloadDerived(payload_size_bytes, rb));
76   const int64_t final_position = rb.Tell();
77 
78   // Read the remaining of the payload (if any) into the footer.
79   if (expected_final_position == final_position) {
80     return absl::OkStatus();
81   } else if (expected_final_position > final_position) {
82     if ((expected_final_position - final_position) % 8 != 0) {
83       return absl::InvalidArgumentError(
84           absl::StrCat("Expected `ReadAndValidatePayloadDerived` to write a "
85                        "multiple of 8 bits for obu_type=",
86                        header_.obu_type));
87     }
88     const int64_t num_bytes_to_read =
89         (expected_final_position - final_position) / 8;
90     footer_.resize(num_bytes_to_read);
91     return rb.ReadUint8Span(absl::MakeSpan(footer_));
92   } else {
93     // The dispatched function read past the end of the payload. Something could
94     // be inconsistent between the parsing logic and the claimed OBU size.
95     return absl::InvalidArgumentError(absl::StrCat(
96         "Read beyond the end of the OBU for obu_type=", header_.obu_type));
97   }
98 }
99 
PrintHeader(int64_t payload_size_bytes) const100 void ObuBase::PrintHeader(int64_t payload_size_bytes) const {
101   // TODO(b/299480731): Use the correct `LebGenerator` when printing OBU
102   //                    headers.
103   header_.Print(*LebGenerator::Create(), payload_size_bytes);
104 }
105 
106 }  // namespace iamf_tools
107