File: v4l2_vp9_helpers_unittest.cc

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (135 lines) | stat: -rw-r--r-- 4,771 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and spanify to fix the errors.
#pragma allow_unsafe_buffers
#endif

#include "media/gpu/v4l2/v4l2_vp9_helpers.h"

#include <vector>

#include "base/containers/span.h"
#include "base/files/memory_mapped_file.h"
#include "media/base/decoder_buffer.h"
#include "media/base/test_data_util.h"
#include "media/parsers/ivf_parser.h"
#include "media/parsers/vp9_parser.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/size.h"

namespace media {
namespace {
// Append |frame_sizes| to |decoder_buffer|'s side_data.
void AppendSideData(DecoderBuffer& decoder_buffer,
                    const std::vector<uint32_t>& frame_sizes) {
  decoder_buffer.WritableSideData().spatial_layers = frame_sizes;
}
}  // namespace

// Checks superframe index size is expected.
TEST(V4L2VP9HelpersTest, CheckSuperFrameIndexSize) {
  constexpr uint32_t kFrameSizes[] = {
      0x10,       // 1 byte
      0x1020,     // 2 byte
      0x010203,   // 3 byte
      0x01020304  // 4 byte
  };

  constexpr size_t kNumFrames = std::size(kFrameSizes);
  for (size_t mask = 1; mask < (1 << kNumFrames) - 1; mask++) {
    size_t buffer_size = 0;
    size_t expected_bytes_per_framesize = 0;
    std::vector<uint32_t> frame_sizes;
    for (size_t i = 0; i < kNumFrames; i++) {
      if (!(mask & (1 << i))) {
        continue;
      }
      frame_sizes.push_back(kFrameSizes[i]);
      buffer_size += kFrameSizes[i];
      expected_bytes_per_framesize = i + 1;
    }

    // Since we don't care the buffer content, the buffer is zero except VP9
    // frame marker.
    std::vector<uint8_t> tmp_buffer(buffer_size);
    size_t offset = 0;
    for (const uint32_t frame_size : frame_sizes) {
      uint8_t* header = tmp_buffer.data() + offset;
      *header = 0x8f;
      offset += frame_size;
    }
    auto decoder_buffer = DecoderBuffer::CopyFrom(tmp_buffer);
    AppendSideData(*decoder_buffer, frame_sizes);

    AppendVP9SuperFrameIndex(decoder_buffer);
    if (frame_sizes.size() == 1) {
      EXPECT_EQ(decoder_buffer->size(), buffer_size);
      continue;
    }

    EXPECT_GT(decoder_buffer->size(), buffer_size);
    size_t superframe_index_size = decoder_buffer->size() - buffer_size;
    EXPECT_EQ(superframe_index_size,
              2 + expected_bytes_per_framesize * frame_sizes.size());
  }
}

TEST(V4L2VP9HelpersTest, ParseAppendedSuperFrameIndex) {
  auto stream = std::make_unique<base::MemoryMappedFile>();
  ASSERT_TRUE(stream->Initialize(GetTestDataFilePath("test-25fps.vp9")));

  // Read three frames from test-25fps.vp9.
  IvfParser ivf_parser;
  IvfFileHeader ivf_file_header;
  ASSERT_TRUE(ivf_parser.Initialize(stream->data(), stream->length(),
                                    &ivf_file_header));
  ASSERT_EQ(ivf_file_header.fourcc, 0x30395056u);  // VP90

  constexpr size_t kNumBuffers = 3;
  std::vector<base::span<const uint8_t>> buffers(3);
  for (size_t i = 0; i < kNumBuffers; i++) {
    IvfFrameHeader ivf_frame_header;
    const uint8_t* ivf_payload;
    ASSERT_TRUE(ivf_parser.ParseNextFrame(&ivf_frame_header, &ivf_payload));
    buffers[i] = base::span(ivf_payload, ivf_frame_header.frame_size);
  }

  std::vector<uint32_t> frame_sizes;
  std::vector<uint8_t> merged_buffer;
  for (size_t i = 0; i < kNumBuffers; ++i) {
    frame_sizes.push_back(buffers[i].size());

    // |merged_buffer| is composed of [0, i] frames.
    const size_t offset = merged_buffer.size();
    merged_buffer.resize(offset + buffers[i].size());
    memcpy(merged_buffer.data() + offset, buffers[i].data(), buffers[i].size());

    auto decoder_buffer = DecoderBuffer::CopyFrom(merged_buffer);
    AppendSideData(*decoder_buffer, frame_sizes);

    AppendVP9SuperFrameIndex(decoder_buffer);
    Vp9Parser vp9_parser;
    auto decoder_buffer_span = base::span(*decoder_buffer);
    vp9_parser.SetStream(decoder_buffer_span.data(), decoder_buffer_span.size(),
                         /*stream_config=*/nullptr);

    // Parse the merged buffer with the created superframe index.
    for (size_t j = 0; j <= i; j++) {
      Vp9FrameHeader frame_header;
      gfx::Size allocate_size;
      std::unique_ptr<DecryptConfig> frame_decrypt_config;
      EXPECT_EQ(vp9_parser.ParseNextFrame(&frame_header, &allocate_size,
                                          &frame_decrypt_config),
                Vp9Parser::Result::kOk);

      EXPECT_EQ(frame_header.data.size(), buffers[j].size());
      // show_frame is 1 if and only if the frame is in the top spatial layer.
      EXPECT_EQ(frame_header.show_frame, j == i);
    }
  }
}

}  // namespace media