-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #63 from quietvoid/capi_rework
Create C API and refactor dolby_vision crate
- Loading branch information
Showing
50 changed files
with
2,334 additions
and
806 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,5 @@ target | |
/*.ffindex | ||
/*.json | ||
/*.xml | ||
Cargo.lock | ||
Cargo.lock | ||
.vscode |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,4 @@ target | |
/*.ffindex | ||
/*.json | ||
/*.xml | ||
Cargo.lock | ||
Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,44 @@ | ||
[package] | ||
name = "dolby_vision" | ||
version = "1.1.0" | ||
version = "1.2.0" | ||
authors = ["quietvoid"] | ||
edition = "2018" | ||
license = "MIT" | ||
description = "Dolby Vision metadata parsing and writing" | ||
repository = "https://github.com/quietvoid/dovi_tool" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
bitvec_helpers = "0.1.0" | ||
anyhow = "1.0" | ||
bitvec = "0.20.4" | ||
crc = { version = "2.0.0", "optional" = true } | ||
hevc_parser = { version = "0.2.0", "optional" = true } | ||
crc = "2.0.0" | ||
serde = { version = "1.0.126", features = ["derive"], "optional" = true } | ||
serde_json = { version = "1.0.64", features = ["preserve_order"], "optional" = true } | ||
roxmltree = { version = "0.14.1", optional = true } | ||
|
||
libc = { version = "0.2", optional = true } | ||
|
||
[features] | ||
hevc_rpu = ["hevc_parser", "crc"] | ||
xml = ["roxmltree"] | ||
serde_feature = ["serde", "serde_json"] | ||
capi = ["libc"] | ||
|
||
[package.metadata.docs.rs] | ||
all-features = true | ||
all-features = true | ||
|
||
[workspace] | ||
members = ["."] | ||
|
||
[package.metadata.capi.header] | ||
subdirectory = "libdovi" | ||
name = "rpu_parser" | ||
|
||
[package.metadata.capi.pkg_config] | ||
strip_include_path_components = 1 | ||
subdirectory = false | ||
name = "dovi" | ||
filename = "dovi" | ||
|
||
[package.metadata.capi.library] | ||
rustflags = "-Cpanic=abort" | ||
name = "dovi" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,17 @@ | ||
Library to read & write Dolby Vision metadata. | ||
Library to read & write Dolby Vision metadata. | ||
|
||
### Building the C-API | ||
|
||
To build and install it you can use [cargo-c](https://crates.io/crates/cargo-c): | ||
|
||
```sh | ||
cargo install cargo-c | ||
cargo cinstall --release | ||
``` | ||
|
||
### Running the C-API example | ||
```sh | ||
cd examples | ||
gcc capi.c -ldovi -o capi_example.o | ||
./capi_example.o | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
header = "// SPDX-License-Identifier: MIT" | ||
sys_includes = ["stddef.h", "stdint.h", "stdlib.h", "stdbool.h"] | ||
no_includes = true | ||
include_guard = "DOVI_H" | ||
tab_width = 4 | ||
style = "Type" | ||
language = "C" | ||
cpp_compat = true | ||
|
||
[parse] | ||
parse_deps = false | ||
|
||
[export] | ||
item_types = ["constants", "enums", "structs", "unions", "typedefs", "opaque", "functions"] | ||
prefix = "Dovi" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,249 @@ | ||
#include <stdio.h> | ||
#include <stdint.h> | ||
#include <inttypes.h> | ||
|
||
#include <libdovi/rpu_parser.h> | ||
|
||
int do_something(DoviRpuOpaque *rpu, const DoviRpuDataHeader *header); | ||
int process_rpu_data_mapping(DoviRpuOpaque *rpu, const DoviRpuDataHeader *header); | ||
int process_dm_metadata(DoviRpuOpaque *rpu, const DoviRpuDataHeader *header); | ||
|
||
const uint8_t* read_rpu_file(char *path, size_t *len); | ||
|
||
int main(void) { | ||
char *path = "../../assets/tests/data_before_crc32.bin"; | ||
int ret; | ||
|
||
size_t length; | ||
const uint8_t *buf = read_rpu_file(path, &length); | ||
|
||
DoviRpuOpaque *rpu = dovi_parse_unspec62_nalu(buf, length); | ||
free((void *) buf); | ||
|
||
// The RPU header is always present | ||
const DoviRpuDataHeader *header = dovi_rpu_get_header(rpu); | ||
if (!header) { | ||
const char *error = dovi_rpu_get_error(rpu); | ||
printf("%s\n", error); | ||
|
||
dovi_rpu_free(rpu); | ||
return 0; | ||
} | ||
|
||
// Process the RPU.. | ||
ret = do_something(rpu, header); | ||
|
||
if (ret < 0) { | ||
const char *error = dovi_rpu_get_error(rpu); | ||
printf("%s\n", error); | ||
} | ||
|
||
// Free everything | ||
dovi_rpu_free_header(header); | ||
dovi_rpu_free(rpu); | ||
} | ||
|
||
int do_something(DoviRpuOpaque *rpu, const DoviRpuDataHeader *header) { | ||
const char *error; | ||
int ret; | ||
|
||
if (header->rpu_type != 2) | ||
return 0; | ||
|
||
// We have new rpu_data_mapping metadata | ||
if (!header->use_prev_vdr_rpu_flag) { | ||
ret = process_rpu_data_mapping(rpu, header); | ||
} | ||
|
||
// We have display management metadata | ||
if (header->vdr_dm_metadata_present_flag) { | ||
ret = process_dm_metadata(rpu, header); | ||
} | ||
|
||
// Convert FEL to MEL | ||
ret = dovi_convert_rpu_with_mode(rpu, 1); | ||
if (ret < 0) { | ||
return -1; | ||
} | ||
|
||
const DoviData *data = dovi_write_unspec62_nalu(rpu); | ||
if (!data) { | ||
return -1; | ||
} | ||
|
||
// Do something with the encoded RPU.. | ||
|
||
// Free the encoded data when we're done | ||
dovi_data_free(data); | ||
|
||
return 0; | ||
} | ||
|
||
int process_rpu_data_mapping(DoviRpuOpaque *rpu, const DoviRpuDataHeader *header) { | ||
const DoviRpuDataMapping *rpu_data_mapping = dovi_rpu_get_data_mapping(rpu); | ||
if (!rpu_data_mapping) | ||
return -1; | ||
|
||
printf("vdr_rpu_data_mapping()\n"); | ||
|
||
// Use the rpu_data_mapping metadata.. | ||
for (int cmp = 0; cmp < DoviNUM_COMPONENTS; cmp++) { | ||
printf(" cmp %d\n", cmp); | ||
|
||
// 1D buffer example | ||
printf(" num_pivots: %d\n", header->num_pivots_minus_2[cmp] + 2); | ||
printf(" values: [", cmp); | ||
|
||
const uint64_t *buf = header->pred_pivot_value[cmp].data; | ||
for (int i= 0; i < header->pred_pivot_value[cmp].len; i++) { | ||
printf(" %d", buf[i]); | ||
} | ||
printf(" ]\n"); | ||
|
||
// 2D buffer example | ||
const DoviU64Data2D poly_coef = rpu_data_mapping->poly_coef[cmp]; | ||
printf(" poly_coefs\n"); | ||
|
||
for (int i = 0; i < poly_coef.len; i++) { | ||
const DoviU64Data *dovi_data = poly_coef.list[i]; | ||
printf(" poly_coef[%d], len: %d, values: [", i, dovi_data->len); | ||
|
||
const uint64_t *buf = dovi_data->data; | ||
for (int j = 0; j < dovi_data->len; j++) { | ||
printf(" %d", buf[j]); | ||
} | ||
|
||
printf(" ]\n"); | ||
} | ||
|
||
// 3D buffer example | ||
const DoviU64Data3D mmr_coef = rpu_data_mapping->mmr_coef[cmp]; | ||
printf(" mmr_coefs, len: %d\n", mmr_coef.len); | ||
|
||
for (int i = 0; i < mmr_coef.len; i++) { | ||
const DoviU64Data2D *dovi_data_2d = mmr_coef.list[i]; | ||
printf(" mmr_coef[%d], len: %d, values: [\n", i, dovi_data_2d->len); | ||
|
||
for (int j = 0; j < dovi_data_2d->len; j++) { | ||
const DoviU64Data *dovi_data = dovi_data_2d->list[j]; | ||
printf(" mmr_coef[%d][%d], len: %d, values: [", i, j, dovi_data->len); | ||
|
||
const uint64_t *buf = dovi_data->data; | ||
for (int k = 0; k < dovi_data->len; k++) { | ||
printf(" %d", buf[k]); | ||
} | ||
|
||
printf(" ]\n"); | ||
} | ||
|
||
printf(" ]\n"); | ||
} | ||
} | ||
|
||
dovi_rpu_free_data_mapping(rpu_data_mapping); | ||
|
||
// We have NLQ metadata (and therefore an enhancement layer) | ||
if (header->nlq_method_idc != -1) { | ||
const DoviRpuDataNlq *rpu_data_nlq = dovi_rpu_get_data_nlq(rpu); | ||
if (!rpu_data_nlq) | ||
return -1; | ||
|
||
printf("vdr_rpu_data_nlq()\n"); | ||
|
||
// Do something with the NLQ data.. | ||
const DoviU64Data2D vdr_in_max = rpu_data_nlq->vdr_in_max; | ||
printf(" NLQ data\n vdr_in_max, len: %d\n", vdr_in_max.len); | ||
|
||
for (int i = 0; i < vdr_in_max.len; i++) { | ||
// This buffer is always size 3 | ||
const DoviU64Data *dovi_data = vdr_in_max.list[i]; | ||
|
||
printf(" vdr_in_max[%d], len: %d, values: [%d, %d, %d]\n", i, | ||
dovi_data->len, dovi_data->data[0], dovi_data->data[1], dovi_data->data[2]); | ||
} | ||
|
||
dovi_rpu_free_data_nlq(rpu_data_nlq); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int process_dm_metadata(DoviRpuOpaque *rpu, const DoviRpuDataHeader *header) { | ||
const DoviVdrDmData *dm_data = dovi_rpu_get_vdr_dm_data(rpu); | ||
if (!dm_data) | ||
return -1; | ||
|
||
printf("vdr_dm_data_payload()\n"); | ||
|
||
// Do something with the DM metadata.. | ||
printf(" Mastering display PQ codes: min %.6f max %.6f\n", dm_data->source_min_pq / 4095.0, | ||
dm_data->source_max_pq / 4095.0); | ||
|
||
// We have the frame stats | ||
if (dm_data->st2094_10_metadata.level1) { | ||
const DoviExtMetadataBlockLevel1 *meta = dm_data->st2094_10_metadata.level1; | ||
|
||
// Values are PQ encoded in 12 bit, from 0 to 4095 | ||
printf(" L1 Frame brightness: min %.6f, max %.6f, avg %.6f\n", meta->min_pq / 4095.0, | ||
meta->max_pq / 4095.0, meta->avg_pq / 4095.0); | ||
} | ||
|
||
// We have creative trims | ||
if (dm_data->st2094_10_metadata.level2.len > 0) { | ||
const DoviLevel2BlockList blocks = dm_data->st2094_10_metadata.level2; | ||
printf(" L2 Creative trims, targets: %d\n", dm_data->st2094_10_metadata.level2.len); | ||
|
||
for (int i = 0; i < dm_data->st2094_10_metadata.level2.len; i++) { | ||
const DoviExtMetadataBlockLevel2 *meta = blocks.list[i]; | ||
|
||
printf(" target display brightness PQ code: %.6f\n", meta->target_max_pq / 4095.0); | ||
|
||
// Trim values are from 0 to 4095 | ||
printf(" trim_slope: %d, trim_offset: %d, trim_power: %d\n", meta->trim_slope, | ||
meta->trim_offset, meta->trim_power); | ||
printf(" trim_chroma_weight: %d, trim_saturation_gain: %d, ms_weight: %d\n", | ||
meta->trim_chroma_weight, meta->trim_saturation_gain, meta->ms_weight); | ||
} | ||
} | ||
|
||
// We have active area metadata | ||
if (dm_data->st2094_10_metadata.level5) { | ||
const DoviExtMetadataBlockLevel5 *meta = dm_data->st2094_10_metadata.level5; | ||
|
||
printf(" L5 Active area offsets: top %d, bottom %d, left %d, right %d\n", | ||
meta->active_area_top_offset, meta->active_area_bottom_offset, | ||
meta->active_area_left_offset, meta->active_area_right_offset); | ||
} | ||
|
||
// We have fallback HDR10 metadata | ||
if (dm_data->st2094_10_metadata.level6) { | ||
const DoviExtMetadataBlockLevel6 *meta = dm_data->st2094_10_metadata.level6; | ||
|
||
printf(" L6 Mastering display: min %.4f, max %d\n", | ||
meta->min_display_mastering_luminance / 10000.0, | ||
meta->max_display_mastering_luminance); | ||
|
||
printf(" MaxCLL %d, MaxFALL %d\n", meta->max_content_light_level, | ||
meta->max_frame_average_light_level); | ||
} | ||
|
||
dovi_rpu_free_vdr_dm_data(dm_data); | ||
} | ||
|
||
const uint8_t* read_rpu_file(char *path, size_t *len) { | ||
FILE *fileptr; | ||
uint8_t *buffer; | ||
|
||
fileptr = fopen(path, "rb"); | ||
fseek(fileptr, 0, SEEK_END); | ||
*len = (size_t) ftell(fileptr); | ||
rewind(fileptr); | ||
|
||
size_t size = *len * sizeof(uint8_t); | ||
|
||
buffer = (uint8_t *) malloc(size); | ||
fread(buffer, *len, 1, fileptr); | ||
fclose(fileptr); | ||
|
||
return buffer; | ||
} |
Oops, something went wrong.