diff --git a/vrecord b/vrecord index fa261f70..5ac5d248 100755 --- a/vrecord +++ b/vrecord @@ -2003,10 +2003,12 @@ _lookup_choice(){ # audio codec "24-bit PCM") + _add_mediaconch_rule_set "${AUDIO_CODEC_PCM_TEST}" MIDDLEOPTIONS_PRES+=(-c:a pcm_s24le) MIDDLEOPTIONS_PRES+=(-rf64 auto) AUDIO_EXT='wav' ;; "24-bit FLAC") + _add_mediaconch_rule_set "${AUDIO_CODEC_FLAC_TEST}" MIDDLEOPTIONS_PRES+=(-c:a flac) MIDDLEOPTIONS_PRES+=(-sample_fmt s32) MIDDLEOPTIONS_PRES+=(-bits_per_raw_sample:a 24) @@ -2808,7 +2810,6 @@ CONTAINER_MATROSKA_TEST=' ' CODEC_GENERAL_TEST=' - YUV CFR YUV @@ -2895,6 +2896,52 @@ AUDIO_CODEC_FLAC_TEST=' 24 ' + +CONTAINER_MP4_TEST=' + mp4 + MPEG-4 + Base Media +' + +CODEC_H264_TEST=' + AVC + 4:2:0 + Progressive + CFR +' + +STANDARD_NTSC_ACCESS_DEINTERLACED_TEST=' + + 480 + 720 + 29.970 + Progressive + BT.601 NTSC + BT.601 + +' + +STANDARD_PAL_ACCESS_DEINTERLACED_TEST=' + + 576 + 720 + 25.000 + Progressive + BT.601 PAL + BT.601 + +' + +AUDIO_CODEC_AAC_TEST=' + AAC + + 1 + 2 + + 48000 +' + + # define mediaconch test fragment -end _start_mediaconch_policy(){ @@ -2903,6 +2950,7 @@ cat < "${MEDIACONCH_POLICY_TMP}" This policy tests FFV1 Matroska and Quicktime files made using vrecord and checks their validity + This policy tests video files made using vrecord and checks their validity against vrecord's specifications MC_START } @@ -2920,6 +2968,65 @@ _add_mediaconch_rule_set(){ fi } +_check_access_mp4_mediaconch() { + if [[ "${MP4_CHOICE}" = "true" ]] && [[ -f "${MP4NAME}" ]] && "${MEDIACONCH_INSTALLED}" ; then + _report -d "Checking access MP4 conformance against a mediaconch policy..." + MP4_POLICY_TMP="$(_maketemp .mediaconch_mp4.xml)" + cat < "${MP4_POLICY_TMP}" + + + This policy tests the access MP4 file made using vrecord and checks its validity against vrecord's access specifications +MC_MP4_START + echo "${CONTAINER_GENERAL_TEST}" >> "${MP4_POLICY_TMP}" + echo "${CONTAINER_MP4_TEST}" >> "${MP4_POLICY_TMP}" + echo "${CODEC_H264_TEST}" >> "${MP4_POLICY_TMP}" + if [[ "${STANDARD}" = "ntsc" ]] ; then + echo "${STANDARD_NTSC_ACCESS_DEINTERLACED_TEST}" >> "${MP4_POLICY_TMP}" + elif [[ "${STANDARD}" = "pal" ]] ; then + echo "${STANDARD_PAL_ACCESS_DEINTERLACED_TEST}" >> "${MP4_POLICY_TMP}" + fi + echo "${AUDIO_CODEC_AAC_TEST}" >> "${MP4_POLICY_TMP}" + cat <> "${MP4_POLICY_TMP}" + + +MC_MP4_END + MP4_REPORT_TMP="$(_maketemp _mediaconch_mp4report.xml)" + MP4_REPORT="${DIR}/${FULL_OUTPUT_ID}_mp4_mediaconch_report.xml" + MP4_POLICY="${DIR}/${FULL_OUTPUT_ID}_mp4_mediaconch_policy.xml" + mediaconch -fx -p "${MP4_POLICY_TMP}" "${MP4NAME}" | xmlstarlet fo > "${MP4_REPORT_TMP}" + MP4_STATUS="$(xmlstarlet sel -N mc="https://mediaarea.net/mediaconch" -t -v mc:MediaConch/mc:media/mc:policy/@outcome -n "${MP4_REPORT_TMP}")" + if [[ "${MP4_STATUS}" = "pass" ]] ; then + _report -dt "Access MP4 passed policy check." + _writeingestlog "mediaconch_mp4_outcome" "passed" + elif [[ "${MP4_STATUS}" = "fail" ]] ; then + _report -wt "The access MP4 file did not pass vrecord policy check." + _mv_tmp_file "${MP4_REPORT_TMP}" "${MP4_REPORT}" + _mv_tmp_file "${MP4_POLICY_TMP}" "${MP4_POLICY}" + _writeingestlog "mediaconch_mp4_outcome" "failed ${MP4_POLICY}" + _report -wt "See ${MP4_REPORT} for a full MediaConch policy report." + _report -wt "Or review this attempt to summarize the issue:" + xmlstarlet edit -N "mc=https://mediaarea.net/mediaconch" -d "//*[@outcome='pass']" "${MP4_REPORT}" | xmlstarlet fo + else + _report -wt "Mediaconch ended in an unexpected way for the access MP4 (status: ${MP4_STATUS})." + _report -wt "${MP4_REPORT_TMP}:" + cat "${MP4_REPORT_TMP}" + _writeingestlog "mediaconch_mp4_outcome" "error ${MP4_STATUS}" + fi + fi +} + +_check_file_truncation() { + TEST_FILE="${1}" + TEST_LABEL="${2}" + if [[ -f "${TEST_FILE}" ]] ; then + IS_TRUNCATED=$(mediainfo --Output=XML "${TEST_FILE}" | xmlstarlet sel -t -v "//*[local-name()='IsTruncated']" -n 2>/dev/null || echo "") + if [[ "${IS_TRUNCATED}" = "Yes" ]] ; then + cowsay "$(_report -w "WARNING: MediaInfo reports that the ${TEST_LABEL} file (${TEST_FILE}) may be truncated or incomplete.")" + fi + _writeingestlog "${TEST_LABEL}_truncated" "${IS_TRUNCATED}" + fi +} + _add_fadgi_header2vtt(){ VTT_FILE="${1}" VTT_TYPE="${2}" @@ -3144,11 +3251,6 @@ if [[ ! "${VIDEO_CODEC_CHOICE}" = "h264" ]] ; then _add_mediaconch_rule_set "${CODEC_GENERAL_TEST}" fi _add_mediaconch_rule_set "${AUDIO_CODEC_GENERAL_TEST}" -if [[ "${AUDIO_CODEC_CHOICE}" = "24-bit PCM" ]] ; then - _add_mediaconch_rule_set "${AUDIO_CODEC_PCM_TEST}" -elif [[ "${AUDIO_CODEC_CHOICE}" = "24-bit FLAC" ]] ; then - _add_mediaconch_rule_set "${AUDIO_CODEC_FLAC_TEST}" -fi # CLI passthrough and audiopassthrough modes if [[ "${RUNTYPE}" = "passthrough" ]] ; then @@ -3247,7 +3349,7 @@ if [[ "${DEVICE_INPUT_CHOICE}" = "0" ]] ; then AUDIOMAP=$(sed "s/0:a:0/1:a:0/g" <<< "$AUDIOMAP") fi if [[ "${MP4_CHOICE}" = "true" ]] ; then - RECORDINGFILTER_MP4+=",bwdif,format=yuv420p" + RECORDINGFILTER_MP4+=",bwdif=send_frame,format=yuv420p" RECORD_COMMAND_MP4+=(-filter_complex "[0:v:0]${RECORDINGFILTER_MP4#,*}[mp4_v_out];${AUDIOMAP_MP4}") MP4NAME="${DIR}/${FULL_OUTPUT_ID}.mp4" EXTRAOUTPUTS+=("${MIDDLEOPTIONS_ALL[@]}" -movflags write_colr+faststart "${RECORD_COMMAND_MP4[@]}" -c:v h264 -g 12 -profile:v main -level "${ACCESS_MP4_LEVEL}" -b:v "${ACCESS_MP4_BITRATE}" -c:a aac -map "[mp4_v_out]" "${AUDIO_CHANNEL_MAP[@]:2}" "${MP4NAME}") @@ -3564,26 +3666,40 @@ if [[ "${DEVICE_INPUT_CHOICE}" = 0 ]] ; then _writeingestlog "Decklink input buffer overrun" "Yes" fi - # policy checks with mediaconch - if "$MEDIACONCH_INSTALLED" ; then + # mediaconch policy check on the preservation output + if "${MEDIACONCH_INSTALLED}" ; then _report -d "Checking file conformance against a mediaconch policy..." - STATUS=$(mediaconch -fx -p "${MEDIACONCH_POLICY_TMP}" "${VRECORD_OUTPUT}" | xmlstarlet sel -N mc="https://mediaarea.net/mediaconch" -t -v mc:MediaConch/mc:media/mc:policy/@outcome -n) + MEDIACONCH_REPORT="${DIR}/${FULL_OUTPUT_ID}_mediaconch_report.xml" + MEDIACONCH_REPORT_TMP="$(_maketemp _mediaconch_report.xml)" + MEDIACONCH_POLICY="${DIR}/${FULL_OUTPUT_ID}_mediaconch_policy.xml" + mediaconch -fx -p "${MEDIACONCH_POLICY_TMP}" "${VRECORD_OUTPUT}" | xmlstarlet fo > "${MEDIACONCH_REPORT_TMP}" + STATUS="$(xmlstarlet sel -N mc="https://mediaarea.net/mediaconch" -t -v mc:MediaConch/mc:media/mc:policy/@outcome -n "${MEDIACONCH_REPORT_TMP}")" if [[ "${STATUS}" = "pass" ]] ; then _report -dt "File passed policy check for the video." _writeingestlog "mediaconch_outcome" "passed" elif [[ "${STATUS}" = "fail" ]] ; then _report -wt "File did not pass vrecord policy check and may not conform to digital preservation standards." - mediaconch -fx -p "${MEDIACONCH_POLICY_TMP}" "${VRECORD_OUTPUT}" | xmlstarlet fo > "${DIR}/${FULL_OUTPUT_ID}_mediaconchreport.xml" - _mv_tmp_file "${MEDIACONCH_POLICY_TMP}" "${DIR}/${FULL_OUTPUT_ID}_mediaconch_policy.xml" - _writeingestlog "mediaconch_outcome" "failed ${DIR}/${FULL_OUTPUT_ID}_mediaconch_policy.xml" - _report -wt "See ${DIR}/${FULL_OUTPUT_ID}_mediaconchreport.xml for a full MediaConch policy report." + _mv_tmp_file "${MEDIACONCH_REPORT_TMP}" "${MEDIACONCH_REPORT}" + _mv_tmp_file "${MEDIACONCH_POLICY_TMP}" "${MEDIACONCH_POLICY}" + _writeingestlog "mediaconch_outcome" "failed ${MEDIACONCH_POLICY}" + _report -wt "See ${MEDIACONCH_REPORT} for a full MediaConch policy report." _report -wt "Or review this attempt to summarize the issue:" - xmlstarlet edit -N "mc=https://mediaarea.net/mediaconch" -d "//*[@outcome='pass']" "${DIR}/${FULL_OUTPUT_ID}_mediaconchreport.xml" + xmlstarlet edit -N "mc=https://mediaarea.net/mediaconch" -d "//*[@outcome='pass']" "${MEDIACONCH_REPORT}" | xmlstarlet fo else - _report -wt "Mediaconch ended in an unexpected way (${STATUS}). Here is its output." - mediaconch -p "${MEDIACONCH_POLICY_TMP}" "${VRECORD_OUTPUT}" + _report -wt "Mediaconch ended in an unexpected way (status: ${STATUS}). Here is its output." + _report -wt "${MEDIACONCH_REPORT}:" + cat "${MEDIACONCH_REPORT}" + _writeingestlog "mediaconch_outcome" "error ${STATUS}" fi fi + # mediaconch policy check on the access MP4 + _check_access_mp4_mediaconch + + # check file truncation + _check_file_truncation "${VRECORD_OUTPUT}" "preservation" + if [[ "${MP4_CHOICE}" = "true" ]] && [[ -f "${MP4NAME}" ]] ; then + _check_file_truncation "${MP4NAME}" "access_mp4" + fi # embed logs in Matroska files if "$MKVPROPEDIT_INSTALLED" ; then