blob: 6c1a0383034e47f9df3d5e1c2fc1ab38c80da3ac [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <openssl/sha.h>
#include "../raw_frames.h"
#include <lib/async-loop/cpp/loop.h>
#include <lib/component/cpp/startup_context.h>
#include <lib/fxl/command_line.h>
#include <lib/fxl/log_settings.h>
#include <lib/fxl/log_settings_command_line.h>
#include <lib/fxl/logging.h>
#include <lib/media/test/frame_sink.h>
constexpr char kInputFilePath[] = "/pkg/data/bear_320x192_40frames.yuv";
constexpr char kGoldenSha[SHA256_DIGEST_LENGTH * 2 + 1] =
"67fdc1fed9bfbf9d1852137ba51bbda661fbf3483f5f47a553a44895de76de98";
// TODO(turnage): Unify media hashing functions in test library.
void SHA256_Update_VideoPlane(SHA256_CTX* sha256_ctx, uint8_t* start,
uint32_t width, uint32_t stride,
uint32_t height) {
uint8_t* src = start;
for (uint32_t row = 0; row < height; ++row) {
SHA256_Update(sha256_ctx, src, width);
src += stride;
}
}
void SHA256_Char_Digest(SHA256_CTX* sha256_ctx, char* digest_str) {
uint8_t digest[SHA256_DIGEST_LENGTH];
SHA256_Final(digest, sha256_ctx);
for (uint8_t byte : digest) {
// Writes the terminating 0 each time, returns 2 each time.
digest_str += snprintf(digest_str, 3, "%02x", byte);
}
}
int HashFrames(RawFrames&& raw_frames) {
SHA256_CTX sha256_ctx;
SHA256_Init(&sha256_ctx);
size_t i = 0;
std::optional<RawFrames::Image> frame;
while ((frame = raw_frames.Frame(i++))) {
// Y
SHA256_Update_VideoPlane(
&sha256_ctx,
/*start=*/frame->image_start + frame->format.primary_start_offset,
frame->format.primary_width_pixels,
frame->format.primary_line_stride_bytes,
frame->format.primary_height_pixels);
// V
SHA256_Update_VideoPlane(
&sha256_ctx,
/*start=*/frame->image_start + frame->format.secondary_start_offset,
frame->format.secondary_width_pixels,
frame->format.secondary_line_stride_bytes,
frame->format.secondary_height_pixels);
// U
SHA256_Update_VideoPlane(
&sha256_ctx,
/*start=*/frame->image_start + frame->format.tertiary_start_offset,
frame->format.secondary_width_pixels,
frame->format.secondary_line_stride_bytes,
frame->format.secondary_height_pixels);
}
char digest_str[SHA256_DIGEST_LENGTH * 2 + 1];
SHA256_Char_Digest(&sha256_ctx, digest_str);
int delta = memcmp(digest_str, kGoldenSha, SHA256_DIGEST_LENGTH);
if (delta) {
fprintf(stderr, "The golden sha is: %s\n", kGoldenSha);
fprintf(stderr, "The video sha is: %s\n", digest_str);
}
return delta == 0 ? 0 : -1;
}
int SendFramesToScenic(RawFrames&& raw_frames) {
async::Loop main_loop(&kAsyncLoopConfigAttachToThread);
std::unique_ptr<component::StartupContext> startup_context =
component::StartupContext::CreateFromStartupInfo();
auto send_frames = [&main_loop, &raw_frames](FrameSink* frame_sink) {
std::optional<RawFrames::Image> frame;
size_t frames_sent = 0;
while ((frame = raw_frames.Frame(frames_sent++))) {
auto domain = std::make_unique<fuchsia::media::DomainFormat>();
domain->video().set_uncompressed(std::move(frame->format));
auto config = std::make_shared<fuchsia::media::StreamOutputConfig>();
config->format_details =
fuchsia::media::FormatDetails{.domain = std::move(domain)};
frame_sink->PutFrame(frames_sent, frame->vmo, frame->vmo_offset, config,
[] {});
}
frame_sink->PutEndOfStreamThenWaitForFramesReturnedAsync(
[&main_loop] { main_loop.Shutdown(); });
};
auto frame_sink = FrameSink::Create(startup_context.get(), &main_loop, 24.0,
std::move(send_frames));
if (!frame_sink) {
FXL_LOG(FATAL) << "Failed to create FrameSink.";
}
main_loop.Run();
return 0;
}
// To see frames manually, run
/*
fx shell set_root_view \
fuchsia-pkg://fuchsia.com/raw_frames_test#meta/raw_frames_test.cmx \
--imagepipe
*/
// Otherwise, the frames will be compared automatically against a sha.
int main(int argc, char** argv) {
auto command_line = fxl::CommandLineFromArgcArgv(argc, argv);
if (!fxl::SetLogSettingsFromCommandLine(command_line)) {
FXL_LOG(FATAL) << "Failed to parse log settings.";
}
auto raw_frames =
RawFrames::FromI420File(kInputFilePath, {
.width = 320,
.height = 192,
.stride = 320,
.frame_alignment = 1024 * 4,
});
if (!raw_frames) {
FXL_LOG(FATAL) << "Failed to parse raw frames from file.";
}
if (command_line.HasOption("imagepipe")) {
return SendFramesToScenic(std::move(*raw_frames));
}
return HashFrames(std::move(*raw_frames));
}