Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Treat avifenc --stdin as regular file input arg #2574

Merged
merged 4 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ The changes are relative to the previous release, unless the baseline is specifi
avifCropRectFromCleanApertureBox() and avifCleanApertureBoxFromCropRect().
* Ignore descriptive properties associated after transformative ones.
* Reject non-essential transformative properties.
* Treat avifenc --stdin as a regular positional file path argument.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't read the pull request. I have a question: where is the position of this fictitious file path argument?

Here is my expectation:

  • If the output file path is specified without using the -o option, the fictitious input file path argument is right before the output file path argument.
  • If the -o option is used, the fictitious input file path argument is at the end of the command line.

Is this what you implemented?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have now read the pull request. What you implemented is not exactly the same as what I expected in how the options with update suffix (i.e., pendingSettings) are handled. This is perfectly fine because there are several reasonable ways to handle this. Since people's expectations may be different from what is implemented, it would be good to document somewhere how we handle the options with update suffix when --stdin is specified.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes no sense to use :u with --stdin because no other input is allowed. So how :u behaves with --stdin does not matter, as long as nothing is silently ignored.

I find it simpler to understand and to implement if --stdin can just be replaced with /path/to/in.y4m with identical behavior. I do not think it has to be mentioned in --help because there is no other input file name allowed, so it does not really matter where --stdin is.

Happy to revisit if needed though.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it's easier to understand if --stdin can be replaced with /path/to/in.y4m with identical behavior. This simple rule is only mentioned in the changelog. It would be good to document this in the help message.

Also, this rule needs to make an exception for the avifenc out.avif --stdin case. The exception might be worth documenting.

Copy link
Collaborator Author

@y-guyon y-guyon Jan 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to document this in the help message.

I disagree. It does not provide any benefit as long as "No other input is allowed": since there is an ovious single input and a single output, the order of all arguments should not matter. The same behavior as if replaced by a file path is somewhat expected (besides the exception you mentioned), and if it is not the case, it does not really matter because there is a single input and a single output.
So describing that in the help message would just bring confusion in my opinion.


## [1.1.1] - 2024-07-30

Expand Down
278 changes: 177 additions & 101 deletions apps/avifenc.c

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ if(AVIF_BUILD_APPS)
add_test(NAME test_cmd_progressive COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/test_cmd_progressive.sh ${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/data
)
add_test(NAME test_cmd_stdin COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/test_cmd_stdin.sh ${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/data
)
add_test(NAME test_cmd_targetsize COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/test_cmd_targetsize.sh ${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/data
)
Expand Down Expand Up @@ -378,7 +381,9 @@ if(AVIF_CODEC_AVM_ENABLED)

if(AVIF_BUILD_APPS)
# Disable all tests that use avifenc without explicitly setting --codec=avm.
set_tests_properties(test_cmd test_cmd_animation test_cmd_grid test_cmd_targetsize PROPERTIES DISABLED True)
set_tests_properties(
test_cmd test_cmd_animation test_cmd_grid test_cmd_stdin test_cmd_targetsize PROPERTIES DISABLED True
)
endif()
endif()
endif()
Expand Down
12 changes: 12 additions & 0 deletions tests/data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,18 @@ License: [same as libavif](https://github.com/AOMediaCodec/libavif/blob/main/LIC

Source: Random frames generated with libavif.

### File [webp_logo_animated.y4m](webp_logo_animated.y4m)

![](webp_logo_animated.y4m)

License: [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/),
[Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0)

Attribution: Google LLC

Source: https://en.wikipedia.org/wiki/File:WebPLogo.svg with text stripped and
animated effects.

# Other Test Files

### File [sRGB2014.icc](sRGB2014.icc)
Expand Down
21 changes: 21 additions & 0 deletions tests/data/webp_logo_animated.y4m

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion tests/test_cmd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ OUT_MSG="avif_test_cmd_out_msg.txt"
# Cleanup
cleanup() {
pushd ${TMP_DIR}
rm -f -- "${ENCODED_FILE}" "${ENCODED_FILE_WITH_DASH}" "${DECODED_FILE}" "${OUT_MSG}"
rm -f -- "${ENCODED_FILE}" "${ENCODED_UTF8_FILE}" "${ENCODED_FILE_REFERENCE}" \
"${ENCODED_FILE_WITH_DASH}" "${DECODED_FILE}" "${DECODED_UTF8_FILE}" \
"${OUT_MSG}"
y-guyon marked this conversation as resolved.
Show resolved Hide resolved
popd
}
trap cleanup EXIT
Expand Down
112 changes: 112 additions & 0 deletions tests/test_cmd_stdin.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/bin/bash
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

source $(dirname "$0")/cmd_test_common.sh

# Input file paths.
INPUT_Y4M_STILL="${TESTDATA_DIR}/kodim03_yuv420_8bpc.y4m"
INPUT_Y4M_ANIMATED="${TESTDATA_DIR}/webp_logo_animated.y4m"
# Output file names.
ENCODED_FILE_REGULAR="avif_test_cmd_stdin_encoded.avif"
ENCODED_FILE_STDIN="avif_test_cmd_stdin_encoded_with_stdin.avif"

# Cleanup
cleanup() {
pushd ${TMP_DIR}
rm -f -- "${ENCODED_FILE_REGULAR}" "${ENCODED_FILE_STDIN}"
popd
}
trap cleanup EXIT

strip_header_if() {
FILE="$1"
STRIP_HEADER="$2"

if ${STRIP_HEADER}; then
# The following does not work on all platforms:
# grep --text mdat "${FILE}"
# awk -b -v RS='mdat' '{print length($0); exit}' "${FILE}"
# Hence the hardcoded variable below.
MDAT_OFFSET=1061
FILE_CONTENTS_AFTER_HEADER=$(tail -c +${MDAT_OFFSET} < "${FILE}")
echo "${FILE_CONTENTS_AFTER_HEADER}" > "${FILE}"
fi
}

test_stdin() {
INPUT_Y4M="$1"
STRIP_HEADER="$2"

# Make sure that --stdin can be replaced with a file path and that it leads to
# the same encoded bytes.

"${AVIFENC}" -s 8 -o "${ENCODED_FILE_REGULAR}" "${INPUT_Y4M}"
"${AVIFENC}" -s 8 -o "${ENCODED_FILE_STDIN}" --stdin < "${INPUT_Y4M}"
strip_header_if "${ENCODED_FILE_REGULAR}" ${STRIP_HEADER}
strip_header_if "${ENCODED_FILE_STDIN}" ${STRIP_HEADER}
cmp --silent "${ENCODED_FILE_REGULAR}" "${ENCODED_FILE_STDIN}"

"${AVIFENC}" -s 9 "${INPUT_Y4M}" -o "${ENCODED_FILE_REGULAR}"
"${AVIFENC}" -s 9 --stdin -o "${ENCODED_FILE_STDIN}" < "${INPUT_Y4M}"
strip_header_if "${ENCODED_FILE_REGULAR}" ${STRIP_HEADER}
strip_header_if "${ENCODED_FILE_STDIN}" ${STRIP_HEADER}
cmp --silent "${ENCODED_FILE_REGULAR}" "${ENCODED_FILE_STDIN}"

"${AVIFENC}" -s 10 "${INPUT_Y4M}" "${ENCODED_FILE_REGULAR}"
"${AVIFENC}" -s 10 --stdin "${ENCODED_FILE_STDIN}" < "${INPUT_Y4M}"
strip_header_if "${ENCODED_FILE_REGULAR}" ${STRIP_HEADER}
strip_header_if "${ENCODED_FILE_STDIN}" ${STRIP_HEADER}
cmp --silent "${ENCODED_FILE_REGULAR}" "${ENCODED_FILE_STDIN}"
"${AVIFENC}" -s 10 "${ENCODED_FILE_STDIN}" --stdin < "${INPUT_Y4M}"
strip_header_if "${ENCODED_FILE_STDIN}" ${STRIP_HEADER}
cmp --silent "${ENCODED_FILE_REGULAR}" "${ENCODED_FILE_STDIN}"

"${AVIFENC}" -s 10 "${INPUT_Y4M}" -q 90 "${ENCODED_FILE_REGULAR}"
"${AVIFENC}" -s 10 --stdin -q 90 "${ENCODED_FILE_STDIN}" < "${INPUT_Y4M}"
strip_header_if "${ENCODED_FILE_REGULAR}" ${STRIP_HEADER}
strip_header_if "${ENCODED_FILE_STDIN}" ${STRIP_HEADER}
cmp --silent "${ENCODED_FILE_REGULAR}" "${ENCODED_FILE_STDIN}"
"${AVIFENC}" -s 10 "${ENCODED_FILE_STDIN}" -q 90 --stdin < "${INPUT_Y4M}"
strip_header_if "${ENCODED_FILE_STDIN}" ${STRIP_HEADER}
cmp --silent "${ENCODED_FILE_REGULAR}" "${ENCODED_FILE_STDIN}"
"${AVIFENC}" -s 10 --stdin "${ENCODED_FILE_STDIN}" -q 90 < "${INPUT_Y4M}"
strip_header_if "${ENCODED_FILE_STDIN}" ${STRIP_HEADER}
cmp --silent "${ENCODED_FILE_REGULAR}" "${ENCODED_FILE_STDIN}"

# Negative tests.

# WARNING: Trailing options with update suffix has no effect. Place them before the input you intend to apply to.
"${AVIFENC}" -s 10 --stdin "${ENCODED_FILE_STDIN}" -q:u 90 < "${INPUT_Y4M}"
cmp --silent "${ENCODED_FILE_REGULAR}" "${ENCODED_FILE_STDIN}" && exit 1

# ERROR: there cannot be any other input if --stdin is specified
"${AVIFENC}" --stdin && exit 1
"${AVIFENC}" --stdin "${INPUT_Y4M}" "${ENCODED_FILE_STDIN}" && exit 1
"${AVIFENC}" "${INPUT_Y4M}" --stdin "${ENCODED_FILE_STDIN}" && exit 1
"${AVIFENC}" "${INPUT_Y4M}" "${ENCODED_FILE_STDIN}" --stdin && exit 1

return 0
}

pushd ${TMP_DIR}
test_stdin "${INPUT_Y4M_STILL}" false

# The output of avifenc for animations is not deterministic because of boxes
# such as mvhd and its field creation_time. Strip the whole header to compare
# only the encoded samples.
test_stdin "${INPUT_Y4M_ANIMATED}" true
popd

exit 0
Loading