avifenc: reject mismatched --depth for Y4M input
diff --git a/apps/avifenc.c b/apps/avifenc.c index 41d7b33..c27eeb7 100644 --- a/apps/avifenc.c +++ b/apps/avifenc.c
@@ -222,7 +222,7 @@ printf(" --mini : EXPERIMENTAL: Use reduced header if possible (backward-incompatible)\n"); #endif printf(" -l,--lossless : Set all defaults to encode losslessly, and emit warnings when settings/input don't allow for it\n"); - printf(" -d,--depth D[,Dextension] : D is the output bit depth per channel. D must be 8, 10 or 12. (JPEG/PNG only; y4m or stdin: bit depth is retained)\n"); + printf(" -d,--depth D[,Dextension] : D is the output bit depth per channel. D must be 8, 10 or 12. (JPEG/PNG only; y4m or stdin: bit depth is retained and must match if specified; Dextension is unsupported)\n"); printf(" If specified, Dextension adds a hidden encoded image of Dextension bit depth in the same file as the primary image to reach 16-bit depth at decoding.\n"); printf(" See avifSampleTransformRecipe for the supported combinations (8,8 and 12,4 and 12,8).\n"); printf(" -y,--yuv FORMAT : Output format, one of 'auto' (default), 444, 422, 420 or 400. Ignored for y4m or stdin (y4m format is retained)\n"); @@ -610,20 +610,21 @@ const avifColorPrimaries colorPrimariesBefore = dstImage->colorPrimaries; const avifTransferCharacteristics transferCharacteristicsBefore = dstImage->transferCharacteristics; - if (avifReadImage(currentFile->filename, - inputFormat, - input->requestedFormat, - input->requestedDepthExtension == 0 ? input->requestedDepth : 16, - chromaDownsampling, - ignoreColorProfile, - ignoreExif, - ignoreXMP, - ignoreGainMap, - UINT32_MAX, - dstImage, - dstDepth, - dstSourceTiming, - &input->frameIter) == AVIF_APP_FILE_FORMAT_UNKNOWN) { + const avifAppFileFormat actualInputFormat = avifReadImage(currentFile->filename, + inputFormat, + input->requestedFormat, + input->requestedDepthExtension == 0 ? input->requestedDepth : 16, + chromaDownsampling, + ignoreColorProfile, + ignoreExif, + ignoreXMP, + ignoreGainMap, + UINT32_MAX, + dstImage, + dstDepth, + dstSourceTiming, + &input->frameIter); + if (actualInputFormat == AVIF_APP_FILE_FORMAT_UNKNOWN) { fprintf(stderr, "ERROR: Couldn't read %s file %s\n", avifFileFormatToString(inputFormat), @@ -633,6 +634,19 @@ } return AVIF_FALSE; } + if (actualInputFormat == AVIF_APP_FILE_FORMAT_Y4M) { + if (input->requestedDepthExtension) { + fprintf(stderr, "ERROR: --depth %d,%d is not supported for Y4M input\n", input->requestedDepth, input->requestedDepthExtension); + return AVIF_FALSE; + } + if (input->requestedDepth && (input->requestedDepth != (int)dstImage->depth)) { + fprintf(stderr, + "ERROR: --depth %d does not match Y4M bit depth %u; Y4M bit-depth conversion is not supported\n", + input->requestedDepth, + dstImage->depth); + return AVIF_FALSE; + } + } if (!allowChangingCicp) { // Restore the previous primaries/transfer in case avifReadImage changed them. dstImage->colorPrimaries = colorPrimariesBefore; @@ -643,7 +657,7 @@ ++input->fileIndex; } if (dstSourceIsRGB) { - *dstSourceIsRGB = (inputFormat != AVIF_APP_FILE_FORMAT_Y4M); + *dstSourceIsRGB = (actualInputFormat != AVIF_APP_FILE_FORMAT_Y4M); } if (dstSettings) { *dstSettings = ¤tFile->settings;
diff --git a/doc/avifenc.1.md b/doc/avifenc.1.md index 52b3311..9989586 100644 --- a/doc/avifenc.1.md +++ b/doc/avifenc.1.md
@@ -54,7 +54,7 @@ : Set all defaults to encode losslessly, and emit warnings when settings/input don't allow for it. **-d**, **\--depth** _D_[,_EXTENSION_] -: D is the output bit depth per channel. D must be 8, 10 or 12. (JPEG/PNG only; y4m or stdin: bit depth is retained). +: D is the output bit depth per channel. D must be 8, 10 or 12. (JPEG/PNG only; y4m or stdin: bit depth is retained and must match if specified; EXTENSION is unsupported). If specified, EXTENSION adds a hidden encoded image of EXTENSION bit depth in the same file as the primary image to reach 16-bit depth at decoding. See avifSampleTransformRecipe for the supported combinations (8,8 and 12,4 and 12,8).
diff --git a/tests/test_cmd.sh b/tests/test_cmd.sh index 2c92707..b9260dd 100755 --- a/tests/test_cmd.sh +++ b/tests/test_cmd.sh
@@ -69,6 +69,11 @@ if [[ ${RET} -ne 1 ]]; then exit 1 fi + "${AVIFENC}" -s 8 --depth 8 "${INPUT_Y4M}" -o "${ENCODED_FILE}" + "${AVIFENC}" -s 8 --depth 8,8 "${INPUT_Y4M}" -o "${ENCODED_FILE}" 2> "${OUT_MSG}" && exit 1 + grep "ERROR: --depth 8,8 is not supported for Y4M input" "${OUT_MSG}" + "${AVIFENC}" -s 8 --depth 10 "${INPUT_Y4M}" -o "${ENCODED_FILE}" 2> "${OUT_MSG}" && exit 1 + grep "ERROR: --depth 10 does not match Y4M bit depth 8" "${OUT_MSG}" # Argument parsing test with filenames starting with a dash. echo "Testing arguments"
diff --git a/tests/test_cmd_stdin.sh b/tests/test_cmd_stdin.sh index af581be..93667ce 100755 --- a/tests/test_cmd_stdin.sh +++ b/tests/test_cmd_stdin.sh
@@ -23,11 +23,12 @@ # Output file names. ENCODED_FILE_REGULAR="avif_test_cmd_stdin_encoded.avif" ENCODED_FILE_STDIN="avif_test_cmd_stdin_encoded_with_stdin.avif" +OUT_MSG="avif_test_cmd_stdin_out_msg.txt" # Cleanup cleanup() { pushd ${TMP_DIR} - rm -f -- "${ENCODED_FILE_REGULAR}" "${ENCODED_FILE_STDIN}" + rm -f -- "${ENCODED_FILE_REGULAR}" "${ENCODED_FILE_STDIN}" "${OUT_MSG}" popd } trap cleanup EXIT @@ -80,6 +81,9 @@ pushd ${TMP_DIR} test_stdin "${INPUT_Y4M_STILL}" y4m + "${AVIFENC}" -s 8 --stdin --input-format y4m --depth 10 -o "${ENCODED_FILE_STDIN}" \ + < "${INPUT_Y4M_STILL}" 2> "${OUT_MSG}" && exit 1 + grep "ERROR: --depth 10 does not match Y4M bit depth 8" "${OUT_MSG}" test_stdin "${INPUT_PNG}" png test_stdin "${INPUT_JPEG}" jpeg