#!/bin/bash

# dependencies: dvrescue, ffmpeg, mediainfo, xmlstarlet

_usage(){
    cat <<EOF
dvpackager

Rewrap a DV stream. This script is part of the dvrescue project.

Usage:
dvpackager [options] file.dv

Options:

 By default, dvpackager will split the output files so that each time
 significant technical characteristics of the dv stream change (such as aspect
 ratio, frame rate, audio channel count, or audio sample rate) a new output file
 will be written. The following flags adjust the way dvpackager will split the
 output.

 -s       (split the output file at recording start markers)
 -d       (split the output file at non-consecutive recording timestamps)
 -t       (split the output file at non-consecutive timecode values)

 -o <dir> (provide a custom output directory)
 -O <pattern>
          (specify a pattern for output files. The following variables may be
           used:
          %FILENAME% - will use the filename of the input file without it's
                       extension
          %RECDATE% -  will use the recording date of the first output frame,
                       in YYYY-MM-DD format. If there is no embedded recording
                       date, then 'XXXX-XX-XX' will be used.
          %RECTIME% -  will use the recording date of the first output frame.
                       If there is no embedded recording date, then
                       'XX-XX-XX' will be used.
          %TC% -       will use the timecode value of the first frame or use
                       XX-XX-XX-XX if no timecode is stored in the first frame.
          %PARTNO% -   This is an incrementing number of the output starting
                       from 1.
           The default pattern is "%FILENAME%_part%PARTNO%". The
           extension of the output file is determined by the -e
           setting.)
               
           Note that if the output pattern would generate multiple output files
           with the same name then a 3-digit incrementing number such as "-001"
           will be added to the end of the filename.
 -e <ext> (specify the extension of the container to use. Tested with:
           mkv, mov, dv. Defaults to mov. Note that using the 'dv' option
           shall simply extract the dv from the file while using the
           selected options to split the output.)
 -l <code>(specify the language code to use for the audio tracks.
           If multiple languages are provided with a comma delimiter such as
           'eng,spa,fra,nor' then they are used for each audio track in order.
           Note that usually could be one or two stereo tracks, but if -m is 
           enabled then it is possible for two or four mono tracks, each
           with it's own language code.)
 -L <code>(specify the language code to use for the caption tracks (if
           any).
 -m       (By default, audio will be handled in stereo pairs, enabling this
           option will arrange the audio into tracks with mono channels.)
 -S       (embeds a caption track if there are captions to represent in the
           source DV)
 -Z       (generate a DVRescue technical subtitle file, which contains
           timecode and other frame-based metadata. This is an experimental
           dvrescue subtitle format)
 -n       (do not repackage, simply generate a dvrescue xml if one doesn't
           already exist, and report on what the output files would be)
 -N <parts> (List the numbers of the segments that should not be packaged.
             Multiple segments numbers may be listed as comma-delimited; for
             instance "-N '1,3'" would output the 2nd segment and any segment
             after the 3rd. Use "-n" to list the segments by number.)
 -v       (shows ffmpeg stderr output, otherwise this is hidden)
 -z       (disable colored terminal output)

 -F <path> (provide a custom ffmpeg path)
 -M <path> (provide a custom mediainfo path)
 -D <path> (provide a custom dvrescue path)
 -X <path> (provide a custom xmlstarlet path)
 -x <path> (provide a custom path to a DVRescue XML that corresponds to the
            input file)
 -V <path> (provide a custom path to a DVRescue technical subtitle file that
            corresponds to the input file, ignored if -S is not set)
 -C <path> (provide a custom path to a DVRescue SCC that corresponds to the
           input file, ignored if -S is not set)

Audio Resample Options

 By default, dvpacakager will preserve the sampling rate of the input DV stream;
 however, if the input contains a mixture of 32000 Hz and 48000 Hz audio, then
 dvpackager will resample the packaged audio to 48000 Hz when muxing to a
 container.

 -3        (Enable this option to keep the sampling rate in its native format.
            Setting this may result in more output files as each change in
            sampling rate will require a new output file. Automatically enabled
            when '-e dv'.)
 -4        (Force all audio to be resampled to 48000 Hz.)
 
 Aspect Ratio Options
 -a <opt>  (Choose a strategy for handling mid-stream changes in aspect ratio.
            Options:
                - n: Split segments for aspect ratio changes.
                - 4: Do not split segments for aspect ratio changes alone,
                     and if packaging a mix of 4/3 and 16/9 content together,
                     then label it as 4/3 in the container.
                - 9: Do not split segments for aspect ratio changes alone,
                     and if packaging a mix of 4/3 and 16/9 content together,
                     then label it as 16/9 in the container.
                - c: Do not split segments for aspect ratio changes alone,
                     and if packaging a mix of 4/3 and 16/9 content together,
                     then label it according the more common aspect ratio in
                     that segment.
            )

 For example, the following command:

 dvpackager -s INPUT.dv

 will read -r INPUT.dv and rewrap those dv frames into an output file while making
 one new output file whenever there is a change in significant technical
 characteristics or frames with recording-start flags.

 dvpackager also has an 'unpackage' mode

 -u       (export the dv stream from each provided file into a single dv stream)

 For example, the following command:

 dvpackager -u INPUT_1.mkv INPUT_2.mkv INPUT_3.mkv

 will create one dv stream that contains all the DV of each input file.

dvpackager also has a method to express a table of how the file would be
repackaged given an XML input.
 
 -T <xml> (provide only a table of information about the output files without
           making any, provide the xml as an argument)

For example, the following command:

dvpackager -s -a c -T file.dv.dvrescue.xml file.dv

will show a table of the outputs for file.dv with the provided options (-s -a c).
EOF
}
if [ "${#}" = 0 ] ; then
    _usage
    exit 0
fi

_maketemp(){
    mktemp -q -t "$(basename "${0}").XXXXXX"
    if [ "${?}" -ne 0 ]; then
        echo "${0}: Can't create temp file, exiting..."
        exit 1
    fi
}

_get_ranges(){
    OPTIND=1
    unset IN_FRAME OUT_FRAME
    while getopts "i:o:q" opt ; do
        case "${opt}" in
          i) IN_FRAME="${OPTARG}" ;;
          o) OUT_FRAME="${OPTARG}" ;;
          q) QUICK="Y" ;;
        esac
    done
    shift "$((OPTIND-1))"
    FRAME_MATCH="d:dvrescue/d:media/d:frames"
    if [[ -n "${1}" ]] ; then
        RANGE_MATCH="${1}"
        RELATIVE_FRAMES="parent::d:frames"
    else
        RANGE_MATCH="${MATCH_FRAMES}"
        RELATIVE_FRAMES="parent::d:frames"
    fi
    if [[ -n "${IN_FRAME}" && "${IN_FRAME}" = "${OUT_FRAME}" ]] ; then
        RANGE_MATCH="${RANGE_MATCH//d:frame/d:frame[@n=${IN_FRAME}]}"
    else
        if [[ -n "${OUT_FRAME}" ]] ; then
            RANGE_MATCH="${RANGE_MATCH//d:frame/d:frame[@n<=${OUT_FRAME}]}"
        fi
        if [[ -n "${IN_FRAME}" ]] ; then
            RANGE_MATCH="${RANGE_MATCH//d:frame/d:frame[@n>=${IN_FRAME}]}"
        fi
    fi
    RANGE_MATCH_FS="$(echo "${RANGE_MATCH}" | cut -s -d "|" -f2- | sed 's|d:|following-sibling::d:|g')"
    if [[ "$QUICK" == "Y" ]] ;then
        "${XMLSTARLET_PATH}" sel -N "d=https://mediaarea.net/dvrescue" -t  -m "${FRAME_MATCH}" -m "${RANGE_MATCH}" \
            --var "p=number((${RANGE_MATCH_FS:-x})[1]/@n)-1" \
            --var "b=(${RANGE_MATCH_FS:-x}|parent::d:frames/following-sibling::d:frames[1]/d:frame[1])[1]/@pos" \
            -v "@pts" -o "|" \
            --if "\$p" -v "(${RANGE_MATCH_FS:-x})[1]/@pts" --else -v "${RELATIVE_FRAMES}/@end_pts" -b -o "|" \
            -v "@n" -o "|" \
            --if "\$p" -v "\$p" --else -v "${RELATIVE_FRAMES}/d:frame[last()]/@n" -b -o "|" \
            -v "@tc" -o "|" \
            -v "@pos" -o "|" \
            -v "@rdt" -o "|" \
            -v "${RELATIVE_FRAMES}/@size" -o "|" \
            --if "${RELATIVE_FRAMES}/@video_rate" -v "${RELATIVE_FRAMES}/@video_rate" --else \
                --if "${RELATIVE_FRAMES}/@size='720x480'" -o "30000/1001" --else \
                --if "${RELATIVE_FRAMES}/@size='720x576'" -o "25" --else -o "30000/1001" -b -b -b -o "|" \
            -v "${RELATIVE_FRAMES}/@chroma_subsampling" -o "|" \
            -v "${RELATIVE_FRAMES}/@aspect_ratio" -o "|" \
            --if "${RELATIVE_FRAMES}[@audio_rate]" -v "${RELATIVE_FRAMES}/@audio_rate" --else -o "0" -b -o "|" \
            --if "${RELATIVE_FRAMES}[@channels]" -v "${RELATIVE_FRAMES}/@channels" --else -o "0" -b -o "|" \
            -v "@rec_start" -o "|" \
            -v "@rdt_nc" -o "|" \
            -v "@tc_nc" -o "|" \
            -o "-|" \
            --if "\$b" -v "\$b" --else -v "ancestor::d:media/@size" -break -o "|" \
            -o "-" \
            -n "${DVRESCUE_XML}"
        # output is pipe-delimited and in this order:
        # 1-2 start pts, end pts
        # 3-4 start frame, end frame
        # 5. timecode
        # 6. offset start
        # 7. recording timestamp
        # 8-11 frame size, frame rate, chroma subsampling, aspect ratio
        # 12-13 sampling rate, channel count
        # 14-16 rec start, recording time jump, timecode jump
        # 17 if ends with missing audio metadata DISABLED
        # 18 offset at end of the range
        # 19 offset of last frame of range DISABLED
    else
        "${XMLSTARLET_PATH}" sel -N "d=https://mediaarea.net/dvrescue" -t  -m "${FRAME_MATCH}" -m "${RANGE_MATCH}" \
            --var "p=number((${RANGE_MATCH_FS:-x})[1]/@n)-1" \
            --var "b=(${RANGE_MATCH_FS:-x}|parent::d:frames/following-sibling::d:frames[1]/d:frame[1])[1]/@pos" \
            -v "@pts" -o "|" \
            --if "\$p" -v "(${RANGE_MATCH_FS:-x})[1]/@pts" --else -v "${RELATIVE_FRAMES}/@end_pts" -b -o "|" \
            -v "@n" -o "|" \
            --if "\$p" -v "\$p" --else -v "${RELATIVE_FRAMES}/d:frame[last()]/@n" -b -o "|" \
            -v "@tc" -o "|" \
            -v "@pos" -o "|" \
            -v "@rdt" -o "|" \
            -v "${RELATIVE_FRAMES}/@size" -o "|" \
            --if "${RELATIVE_FRAMES}/@video_rate" -v "${RELATIVE_FRAMES}/@video_rate" --else \
                --if "${RELATIVE_FRAMES}/@size='720x480'" -o "30000/1001" --else \
                --if "${RELATIVE_FRAMES}/@size='720x576'" -o "25" --else -o "30000/1001" -b -b -b -o "|" \
            -v "${RELATIVE_FRAMES}/@chroma_subsampling" -o "|" \
            -v "${RELATIVE_FRAMES}/@aspect_ratio" -o "|" \
            --if "${RELATIVE_FRAMES}[@audio_rate]" -v "${RELATIVE_FRAMES}/@audio_rate" --else -o "0" -b -o "|" \
            --if "${RELATIVE_FRAMES}[@channels]" -v "${RELATIVE_FRAMES}/@channels" --else -o "0" -b -o "|" \
            -v "@rec_start" -o "|" \
            -v "@rdt_nc" -o "|" \
            -v "@tc_nc" -o "|" \
            --if "\$p" \
                -v "count(//d:frame[@n=\$p]/@no_pack|//d:frame[@n=\$p]/@no_pack_aud|//d:frame[@n=\$p]/@no_sourceorcontrol_aud)" \
            --else \
                -v "count(${RELATIVE_FRAMES}/d:frame[last()]/@no_pack|${RELATIVE_FRAMES}/d:frame[last()]/@no_pack_aud|${RELATIVE_FRAMES}/d:frame[last()]/@no_sourceorcontrol_aud)" \
            --break -o "|" \
            --if "\$b" -v "\$b" --else -v "ancestor::d:media/@size" -break -o "|" \
            --if "\$p" \
                -v "//d:frame[@n=\$p]/@pos" \
            --else \
                -v "${RELATIVE_FRAMES}/d:frame[last()]/@pos" -break \
            -n "${DVRESCUE_XML}"
        # output is pipe-delimited and in this order:
        # 1-2 start pts, end pts
        # 3-4 start frame, end frame
        # 5. timecode
        # 6. offset start
        # 7. recording timestamp
        # 8-11 frame size, frame rate, chroma subsampling, aspect ratio
        # 12-13 sampling rate, channel count
        # 14-16 rec start, recording time jump, timecode jump
        # 17 if ends with missing audio metadata
        # 18 offset at end of the range
        # 19 offset of last frame of range
    fi
}

_ranges_2_table(){
    RANGES="${1}"
    echo
    echo -n "# Segmentation options. Split on: Recording_Start_Marker = ${REC_START_OPT}, Recording_Timestamp_Jump = ${RDT_NC_OPT}, Timecode_Jump = ${TC_NC_OPT}"
    echo -n ", Audio_characteristics_change = "
    if [[ "${CONDENSE_OPTS}" == *"-s"* ]] ; then
        echo -n "0"
    else
        echo -n "1"
    fi
    echo -n ", Aspect_Ratio_change = "
    if [[ "${CONDENSE_OPTS}" == *"-a"* ]] ; then
        echo -n "0"
    else
        echo -n "1"
    fi
    echo
    echo "#         St='Flagged Start of a recording', ncTC='non-continuous timecode value', ncR='non-continuous recording timestamp value'"
    echo "  # | PTS Range                         | Duration | Frame Range         | Byte Range                | Timecode    | Recording Timestamp    | Size      | Frame Rate | DAR   | ChSub | Audio     | St | ncTC | ncR |"
    SEG_PART="1"
    echo "${RANGES}" | while IFS="|" read -r PTS END_PTS FRAME_START FRAME_END TC PKT_POS RDT SIZE VIDEO_RATE CH_SUB AR AUDIO_RATE CH REC_ST RDT_NC TC_NC LAST_FRAME_NO_AUDIO PKT_POS_END PKT_POS_LAST ; do
        DURATION="$(_duration_from_pts_range "${PTS}" "${END_PTS}")"
        SEG2EXPORT="$(_check_if_in_list "${SEG_PART}" "${SEGMENT_SKIPS}")"
        awk -v SEG_PART="${SEG_PART}" -v SEG2EXPORT="${SEG2EXPORT}" -v PTS="${PTS}" -v END_PTS="${END_PTS}" -v FRAME_START="${FRAME_START}" -v FRAME_END="${FRAME_END}" -v TC="${TC}" -v PKT_POS="${PKT_POS}" -v RDT="${RDT}" -v SIZE="${SIZE}" -v VIDEO_RATE="${VIDEO_RATE}" -v CH_SUB="${CH_SUB}" -v AR="${AR}" -v AUDIO_RATE="${AUDIO_RATE}" -v CH="${CH}" -v REC_ST="${REC_ST}" -v RDT_NC="${RDT_NC}" -v TC_NC="${TC_NC}" -v LAST_FRAME_NO_AUDIO="${LAST_FRAME_NO_AUDIO}" -v PKT_POS_END="${PKT_POS_END}" -v PKT_POS_LAST="${PKT_POS_LAST}" -v DURATION="${DURATION}" \
            'END {printf "%3s%1s| %15s - %15s | %8.3f | %8i - %8i | %11i - %11i | %11s | %-22s | %9s | %10s | %5s | %5s | %1sch %5i | %2s | %4s | %3s |\n", \
        SEG_PART, SEG2EXPORT, PTS, END_PTS, DURATION, FRAME_START, FRAME_END, PKT_POS, PKT_POS_END, TC, RDT, SIZE, VIDEO_RATE, AR, CH_SUB, CH, AUDIO_RATE, REC_ST, TC_NC, RDT_NC}' < /dev/null
        ((SEG_PART++))
    done
    echo
}

_ranges_2_output_table(){
    # shows a pipe-delimited table of segment ranges, and adds a new column which predicted output filename.
    RANGES="${1}"
    SEG_INPUT="1"
    SEG_OUTPUT="1"
    if [[ -z "${BASENAME}" && -n "${DVRESCUE_XML}" ]] ; then
        BASENAME="$(basename "${DVRESCUE_XML//.dvrescue.xml/}")"
    fi
    echo "${RANGES}" | while read -r RANGE_LINE ; do
        IFS='|' read -r PTS_START PTS_END FRAME_START FRAME_END TC OFFSET_START RDT FS FR CS AR SR CC RS RTJ TJ EMA OER OLR <<< "${RANGE_LINE}"
        if [[ "$(_check_if_in_list "${SEG_INPUT}" "${SEGMENT_SKIPS}")" != "x" ]] ; then

            # generate output files (this code is reused in the output section)
            APPLIED_PATTERN="$(echo "${OUTPUTPATTERN}" | sed "s|%FILENAME%|${BASENAME%.*}|g;s|%RECDATE%|${RDT:0:4}-${RDT:5:2}-${RDT:8:2}|g;s|%RECTIME%|${RDT:11:2}-${RDT:14:2}-${RDT:17:2}|g;s|%TC%|${TC//[:;]/-}|g;s|%PARTNO%|${SEG_OUTPUT}|g")"
            COLLECTED_OUTPUTS+=(${APPLIED_PATTERN})
            MATCH_NAME_COUNT=0
            for OUTPUT_FILENAME in "${COLLECTED_OUTPUTS[@]}" ; do
                if [[ "${OUTPUT_FILENAME}" = "${APPLIED_PATTERN}" ]]; then
                    (( MATCH_NAME_COUNT++ ))
                fi
            done 
            if [[ "${MATCH_NAME_COUNT}" -gt 1 ]] ; then
                INCREMENT_ADD="-$(echo "${MATCH_NAME_COUNT}-1" | bc -l | awk '{printf "%03d", $0}')"
            else
                INCREMENT_ADD=""
            fi
            OUTPUT_FILE="${SIDECAR_DIR}/${APPLIED_PATTERN}${INCREMENT_ADD}.${EXTENSION}"

            echo "${RANGE_LINE//[$'\t\r\n']}|${OUTPUT_FILE}"
            ((SEG_OUTPUT++))
        fi
        ((SEG_INPUT++))
    done
}

_condense_ranges(){
    # the inputs is pipe-delimited and in this order:
    # 1-2 start pts, end pts
    # 3-4 start frame, end frame
    # 5. timecode
    # 6. offset start
    # 7. recording timestamp
    # 8-11 frame size, frame rate, chroma subsampling, aspect ratio
    # 12-13 sampling rate, channel count
    # 14-16 rec start, recording time jump, timecode jump
    # 17 if ends with missing audio metadata
    # 18 offset at end of the range
    # 19 offset of last frame of range
    OPTIND=1
    unset SAMPLING_FREQ_MERGE ASPECT_MERGE
    while getopts "sa:" opt ; do
        case "${opt}" in
          s) SAMPLING_FREQ_MERGE="Y" ;;
          a) ASPECT_MERGE="${OPTARG}" ;;
        esac
    done
    shift "$((OPTIND-1))"
    _set_first(){
        # store values from beginning of range
        PTS_FIRST="${PTS}" #1
        FRAME_START_FIRST="${FRAME_START}" #3
        TC_FIRST="${TC}" #5
        PKT_POS_FIRST="${PKT_POS}" #6
        RDT_FIRST="${RDT}" #7
        SIZE_FIRST="${SIZE}" #8
        VIDEO_RATE_FIRST="${VIDEO_RATE}" #9
        CH_SUB_FIRST="${CH_SUB}" #10
        AR_FIRST="${AR}" #11
        AUDIO_RATE_FIRST="${AUDIO_RATE}" #12
        CH_FIRST="${CH}" #13
        REC_ST_FIRST="${REC_ST}" #14
        RDT_NC_FIRST="${RDT_NC}" #15
        TC_NC_FIRST="${TC_NC}" #16
        LAST_FRAME_NO_AUDIO_FIRST="${LAST_FRAME_NO_AUDIO}" #17
        PKT_POS_END_FIRST="${PKT_POS_END}" #18
        PKT_POS_LAST_FIRST="${PKT_POS_LAST}" #19
    }
    _set_prev(){
        # store values from previous range
        PTS_PREV="${PTS}" #1
        END_PTS_PREV="${END_PTS}" #2
        FRAME_START_PREV="${FRAME_START}" #3
        FRAME_END_PREV="${FRAME_END}" #4
        TC_PREV="${TC}" #5
        PKT_POS_PREV="${PKT_POS}" #6
        RDT_PREV="${RDT}" #7
        SIZE_PREV="${SIZE}" #8
        VIDEO_RATE_PREV="${VIDEO_RATE}" #9
        CH_SUB_PREV="${CH_SUB}" #10
        AR_PREV="${AR}" #11
        AUDIO_RATE_PREV="${AUDIO_RATE}" #12
        CH_PREV="${CH}" #13
        REC_ST_PREV="${REC_ST}" #14
        RDT_NC_PREV="${RDT_NC}" #15
        TC_NC_PREV="${TC_NC}" #16
        LAST_FRAME_NO_AUDIO_PREV="${LAST_FRAME_NO_AUDIO}" #17
        PKT_POS_END_PREV="${PKT_POS_END}" #18
        PKT_POS_LAST_PREV="${PKT_POS_LAST}" #19
    }
    _report_condensed_line(){
        if [[ -n "${ASPECT_MERGE}" && "${ASPECT_FLIP}" = "Y" ]] ; then
            if [[ "${ASPECT_MERGE}" = "4" ]] ; then
                _report -v "The aspect ratio will be forced to 4/3."
                AR_FORCE="4/3"
            elif [[ "${ASPECT_MERGE}" = "9" ]] ; then
                _report -v "The aspect ratio will be forced to 16/9."
                AR_FORCE="16/9"
            elif [[ "${ASPECT_MERGE}" = "c" ]] ; then
                _report -v "The aspect ratio will be forced to most common occurence. We found ${COUNT_43} frames with 4/3 aspect ratio and ${COUNT_169} frames with 16/9 or will use the greater value (4/3 in a tie)."
                if [[ "${COUNT_43}" -ge "${COUNT_169}" ]] ; then
                    AR_FORCE="4/3"
                else
                    AR_FORCE="16/9"
                fi
            else
                AR_FORCE="4/3"
            fi
        else
            AR_FORCE="${AR_FIRST}"
        fi
        if [[ "${SAMPLING_FREQ_MERGE}" = "Y" ]] ; then
            if [[ "${AUDIO_RATE_FIRST}" = "48000" || "${AUDIO_RATE_PREV}" = "48000" ]] ; then
                SR_FORCE="48000"
            else
                if [[ -n "${FORCE_SAMPLE_RATE}" ]] ; then
                    SR_FORCE="${FORCE_SAMPLE_RATE}"
                else
                    SR_FORCE="${AUDIO_RATE_FIRST}"
                fi
            fi
        else
            if [[ -n "${FORCE_SAMPLE_RATE}" ]] ; then
                SR_FORCE="${FORCE_SAMPLE_RATE}"
            else
                SR_FORCE="${AUDIO_RATE_FIRST}"
            fi
        fi
        if [[ "${CH_FIRST}" = "4" || "${CH_PREV}" = "4" ]] ; then
            CH_FORCE="4"
        elif [[ "${CH_FIRST}" = "2" || "${CH_PREV}" = "2" ]] ; then
            CH_FORCE="2"
        else
            CH_FORCE="0"
        fi
        echo "${PTS_FIRST}|${END_PTS_PREV}|${FRAME_START_FIRST}|${FRAME_END_PREV}|${TC_FIRST}|${PKT_POS_FIRST}|${RDT_FIRST}|${SIZE_FIRST}|${VIDEO_RATE_FIRST}|${CH_SUB_FIRST}|${AR_FORCE}|${SR_FORCE}|${CH_FORCE}|${REC_ST_FIRST}|${RDT_NC_FIRST}|${TC_NC_FIRST}|${LAST_FRAME_NO_AUDIO_FIRST}|${PKT_POS_END_PREV}|${PKT_POS_LAST_PREV}"
    }
    RANGES="${1}"
    unset ASPECT_FLIP
    COUNT_43="0"
    COUNT_169="0"
    RANGE_COUNTER="0"
    RANGE_TOTAL="$(echo "${RANGES}" | grep -c "^")"
    echo "${RANGES}" | while IFS="|" read -r PTS END_PTS FRAME_START FRAME_END TC PKT_POS RDT SIZE VIDEO_RATE CH_SUB AR AUDIO_RATE CH REC_ST RDT_NC TC_NC LAST_FRAME_NO_AUDIO PKT_POS_END PKT_POS_LAST ; do
        ((RANGE_COUNTER++))
        if [[ -z "${PTS_FIRST}" ]] ; then
            _set_first
            _set_prev
        else
            if [[ "${AR_PREV}" = "4/3" ]] ; then
                COUNT_43="$((COUNT_43 + FRAME_END_PREV - FRAME_START_PREV))"
            elif [[ "${AR_PREV}" = "16/9" ]] ; then
                COUNT_169="$((COUNT_169 + FRAME_END_PREV - FRAME_START_PREV))"
            fi
            if [[ \
                "${SAMPLING_FREQ_MERGE}" = "Y" && -z "${ASPECT_MERGE}" && \
                "${SIZE_FIRST}|${VIDEO_RATE_FIRST}|${CH_SUB_FIRST}|${AR_FIRST}" == "${SIZE}|${VIDEO_RATE}|${CH_SUB}|${AR}" && \
                "${REC_START_OPT}" != "${REC_ST}" && \
                "${RDT_NC_OPT}"    != "${RDT_NC}" && \
                "${TC_NC_OPT}"     != "${TC_NC}" \
               ]] ; then
                _set_prev
            elif [[ \
                "${SAMPLING_FREQ_MERGE}" = "Y" && -n "${ASPECT_MERGE}" && \
                "${SIZE_FIRST}|${VIDEO_RATE_FIRST}|${CH_SUB_FIRST}" == "${SIZE}|${VIDEO_RATE}|${CH_SUB}" && \
                "${REC_START_OPT}" != "${REC_ST}" && \
                "${RDT_NC_OPT}"    != "${RDT_NC}" && \
                "${TC_NC_OPT}"     != "${TC_NC}" \
               ]] ; then
                if [[ "${AR_FIRST}" != "${AR}" ]] ; then
                    ASPECT_FLIP="Y"
                fi
                _set_prev
            elif [[ \
                -z "${SAMPLING_FREQ_MERGE}" && -n "${ASPECT_MERGE}" && \
                "${SIZE_FIRST}|${VIDEO_RATE_FIRST}|${CH_SUB_FIRST}" == "${SIZE}|${VIDEO_RATE}|${CH_SUB}" && \
                "${AUDIO_RATE_FIRST}|${CH_FIRST}" == "${AUDIO_RATE}|${CH}" && \
                "${REC_START_OPT}" != "${REC_ST}" && \
                "${RDT_NC_OPT}"    != "${RDT_NC}" && \
                "${TC_NC_OPT}"     != "${TC_NC}" \
                ]] ; then
                if [[ "${AR_FIRST}" != "${AR}" ]] ; then
                    ASPECT_FLIP="Y"
                fi
                _set_prev
            else
                _report_condensed_line
                _set_first
                _set_prev
                unset ASPECT_FLIP
                COUNT_43="0"
                COUNT_169="0"
            fi
        fi
        if [[ "${RANGE_COUNTER}" == "${RANGE_TOTAL}" ]] ; then
            if [[ "${AR_PREV}" = "4/3" ]] ; then
                COUNT_43="$((COUNT_43 + FRAME_END_PREV - FRAME_START_PREV))"
            elif [[ "${AR_PREV}" = "16/9" ]] ; then
                COUNT_169="$((COUNT_169 + FRAME_END_PREV - FRAME_START_PREV))"
            fi
            _report_condensed_line
        fi
    done
}

_convert_hhmmssmmm2s(){
    TS="${1}"
    echo "${TS}" | awk -F ":" '{ printf "%8.6f\n", ($1 * 3600) + ($2 * 60) + $3 }'
}

_duration_from_pts_range(){
    START="${1}"
    END="${2}"
    START_SEC="$(_convert_hhmmssmmm2s "${START}")"
    END_SEC="$(_convert_hhmmssmmm2s "${END}")"
    awk -v S="${START_SEC}" -v E="${END_SEC}" 'END { printf "%8.6f\n", E - S }' < /dev/null
}

_count_dv_frames(){
    if [[ -f "${MEDIAINFO_PATH}" ]] ; then
        INPUT_FILE="${1}"
        "${MEDIAINFO_PATH}" -f --inform="Video;%FrameCount%" "${INPUT_FILE}" | head -n 1 | awk '{printf "%s", $0}'
    else
        _report -w "Warning: Missing mediainfo, dvpackager can still package but some verification checks can not run."
    fi
}

_get_track2_maxdiff(){
    # 1: input dv 2: byte offset 3: duration to read
    "${FFMPEG_PATH}" -nostdin -skip_initial_bytes "${2}" -t "${3}" -probesize 10M -i "${1}" -filter_complex "[0:a:1]astats" -f null -vn - 2>&1 | sed '1,/Overall$/d' | grep "Max difference:" | cut -d ":" -f2- | sed 's/ //g'
}

_check_audio_by_ffmpeg_subfile(){
    # The input should be a subfile input statement
    # The output will be a list of the audio track sample rates, likely "48000" or "3200032000"
    SUBFILE="${1}"
    QUERY="$("${FFMPEG_PATH}" -nostdin -probesize 10M -i "${SUBFILE}" 2>&1 | grep Audio: | grep -o "[0-9]* Hz" | awk '{printf $1}')"
    if [[ "${QUERY}" = "48000" ]] ; then
        echo "2-48000"
    elif [[ "${QUERY}" = "44100" ]] ; then
        echo "2-44100"
    elif [[ "${QUERY}" = "32000" ]] ; then
        echo "2-32000"
    elif [[ "${QUERY}" = "4800032000" || "${QUERY}" = "4410032000" ]] ; then
        # ffmpeg is being weird here
        echo "4-32000"
    elif [[ "${QUERY}" = "3200032000" ]] ; then
        echo "4-32000"
    elif [[ -z "$QUERY" ]] ; then
        echo "0" 
    else
        _report -w "Error: there was an unexpected result (${QUERY}) from ffmpeg when querying the audio. Please consider mentioning this at https://github.com/mipops/dvrescue/issues."
        echo "0"
    fi
}

_check_if_in_list(){
    VALUE="${1}"
    LIST="${2}" # list is expected as comma-delimited
    if [[ ",${LIST}," = *",${VALUE},"* ]] ; then
        echo "x"
    else
        echo " "
    fi
}

_make_chapter_metadata_file(){
    OPTIND=1
    while getopts "i:o:s:e:r" opt ; do
        case "${opt}" in
            i) CHAPTER_FRAME_IN="${OPTARG}" ;;
            o) CHAPTER_FRAME_OUT="${OPTARG}" ;;
            s) CHAPTER_PTS_IN="${OPTARG}" ;;
            e) CHAPTER_PTS_OUT="${OPTARG}" ;;
            r) REPORT=true ;;
        esac
    done
    shift "$((OPTIND-1))"
    CHAP_RANGE_START="$(_convert_hhmmssmmm2s "${CHAPTER_PTS_IN}" | awk '{printf "%i", $1 * 100000}')"
    CHAP_RANGE_END="$(_convert_hhmmssmmm2s "${CHAPTER_PTS_OUT}" | awk '{printf "%i", $1 * 100000}')"
    CHAPTER_SETS="$(_get_ranges -i "${CHAPTER_FRAME_IN}" -o "${CHAPTER_FRAME_OUT}" "d:frame[1]|d:frame[@rec_start]|d:frame[@rdt_nc]")"
    CHAPTER_SET_COUNT="$(echo "${CHAPTER_SETS}" | grep -c '^')"
    _report -v "Found ${CHAPTER_SET_COUNT} point(s) for chapter marks."
    if [[ "${CHAPTER_SET_COUNT}" -gt 1 ]] ; then
        echo ";FFMETADATA1"
        echo "${CHAPTER_SETS}" | while IFS="|" read -r PTSc END_PTSc FRAME_STARTc FRAME_ENDc TCc PKT_POSc RDTc SIZEc VIDEO_RATEc CH_SUBc ARc AUDIO_RATEc CHc REC_STc RDT_NCc TC_NCc ; do
             START_CHAPTER="$(_convert_hhmmssmmm2s "${PTSc}" | awk '{printf "%i", $1 * 100000}')"
             END_CHAPTER="$(_convert_hhmmssmmm2s "${END_PTSc}" | awk '{printf "%i", $1 * 100000}')"
             START_CHAPTER_OFFSET="$((START_CHAPTER-CHAP_RANGE_START))"
             END_CHAPTER_OFFSET="$((END_CHAPTER-CHAP_RANGE_START))"
             if [[ "${START_CHAPTER}" -ge "${CHAP_RANGE_START}" ]] && [[ "${END_CHAPTER}" -le "${CHAP_RANGE_END}" ]] ; then
                 unset CHAP_TITLE
                 if [[ -n "${TCc}" ]] && [[ -n "${RDTc}" ]] ; then
                     CHAP_TITLE+="${TCc} - ${RDTc}"
                 elif [[ -n "${TCc}" ]] ; then
                     CHAP_TITLE+="${TCc}"
                 elif [[ -n "${RDTc}" ]] ; then
                     CHAP_TITLE+="--:--:--:-- - ${RDTc}"
                 fi
                 _report -v "Chapter: ${PTSc}-${END_PTSc} (${START_CHAPTER_OFFSET}-${END_CHAPTER_OFFSET}): ${CHAP_TITLE}"
                 echo "[CHAPTER]"
                 echo "TIMEBASE=1/100000"
                 echo "START=${START_CHAPTER_OFFSET}"
                 echo "END=${END_CHAPTER_OFFSET}"
                 echo "title=${CHAP_TITLE}"
             fi
        done
    else
        _report -v "Skipping the process to embed chapters since there would only be one."
    fi
}

_get_iso8601(){
    date +%FT%T
}

_report(){
    if [[ "${DISABLE_COLORED_LOGGING}" != "Y" ]] ; then
        local RED="$(tput setaf 1)"    # Red      - For Warnings
        local GREEN="$(tput setaf 2)"  # Green    - For Declarations
        local BLUE="$(tput setaf 4)"   # Blue     - For Questions
        local MAGENTA="$(tput setaf 5)" # Magenta - For Verbose Statements
        local NC="$(tput sgr0)"        # No Color
    fi
    local COLOR=""
    local STARTMESSAGE=()
    local ECHOOPT=""
    local VERBOSE_CHECK=false
    OPTIND=1
    while getopts "vqdwstn" opt ; do
        case "${opt}" in
            v) VERBOSE_CHECK=true ;
               COLOR="${MAGENTA}" ;
               STARTMESSAGE+="#" ;; # only output the message if DV_VERBOSE=true
            q) COLOR="${BLUE}" ;;                        # question mode, use color blue
            d) COLOR="${GREEN}" ;;                       # declaration mode, use color green
            w) COLOR="${RED}" ;;                         # warning mode, use color red
            s) STARTMESSAGE+=([${SCRIPTNAME}] ) ;;       # prepend scriptname to the message
            t) STARTMESSAGE+=($(_get_iso8601) '- ' ) ;;  # prepend timestamp to the message
            n) ECHOOPT="-n" ;;                           # to avoid line breaks after echo
        esac
    done
    shift "$((OPTIND-1))"
    MESSAGE="${1}"
    if ! "${VERBOSE_CHECK}" || ( "${DV_VERBOSE}" && "${VERBOSE_CHECK}" ) ; then
        if [[ "${DISABLE_COLORED_LOGGING}" = "Y" ]] ; then
            >&2 echo ${ECHOOPT} "${STARTMESSAGE[@]}${MESSAGE}"
        else
            >&2 echo ${ECHOOPT} "${COLOR}${STARTMESSAGE[@]}${MESSAGE}${NC}"
        fi
    fi
}

_get_ffmpeg_path(){
if [[ -x '/Applications/dvrescue.app/Contents/Helpers/ffmpeg' ]] ; then
    FFMPEG_PATH='/Applications/dvrescue.app/Contents/Helpers/ffmpeg'
elif [[ -x '/usr/lib64/dvrescue/bin/ffmpeg' ]] ; then
    FFMPEG_PATH='/usr/lib64/dvrescue/bin/ffmpeg'
elif [[ -x '/usr/lib/dvrescue/bin/ffmpeg' ]] ; then
    FFMPEG_PATH='/usr/lib/dvrescue/bin/ffmpeg'
elif [[ -x '/cygdrive/c/Program Files/dvrescue/ffmpeg.exe' ]] ; then
    FFMPEG_PATH='/cygdrive/c/Program Files/dvrescue/ffmpeg.exe'
else
    FFMPEG_PATH="$(which ffmpeg)"
    _report "dvpackager would prefer to use an ffmpeg bundled with the DVRescue GUI, but can't find one. We'll use ${FFMPEG_PATH} for now, but suggest installing/updating the DVRescue GUI."
fi
if [[ ! -x "${FFMPEG_PATH}" ]] ; then
    _report "ffmpeg can't be found, please install of rerun by ffmpeg's path specified with -F"
    exit 1
fi
}

_get_mediainfo_path(){
if [[ -x '/usr/lib/dvrescue/bin/mediainfo' ]] ; then
    MEDIAINFO_PATH='/usr/lib/dvrescue/bin/mediainfo'
else
    MEDIAINFO_PATH="$(which mediainfo)"
fi
if [[ ! -x "${MEDIAINFO_PATH}" ]] ; then
    _report "mediainfo can't be found, please install of rerun by mediainfo's path specified with -M"
    exit 1
fi
}

MATCH_FRAMES="d:frame[1]|"
FFMPEG_VERBOSE=(-v quiet -stats)
DV_VERBOSE=false
REPORT_ONLY="N"
EXT="mov"
SUBS="N"
TECHSUBS="N"
REC_START_OPT="0"
RDT_NC_OPT="0"
TC_NC_OPT="0"
CONDENSE_OPTS=(-s)
OUTPUTPATTERN="%FILENAME%_part%PARTNO%"

# command-line options to set media id and original variables
OPTIND=1
while getopts ":fsdto:O:e:l:L:mSZnN:vzuhF:M:D:X:x:V:C:34a:T:" opt ; do
    case "${opt}" in
        f) FORCE_FRAMES="Y" ;; # this option has been removed
        s) REC_START_OPT="1" ; MATCH_FRAMES+="d:frame[@rec_start]|" ;;
        d) RDT_NC_OPT="1"    ; MATCH_FRAMES+="d:frame[@rdt_nc]|" ;;
        t) TC_NC_OPT="1"     ; MATCH_FRAMES+="d:frame[@tc_nc]|" ;;
        o) OUTPUTDIR="${OPTARG}" ;;
        O) OUTPUTPATTERN="${OPTARG}" ;;
        e) EXT="${OPTARG}" ;;
        l) LANGUAGES="${OPTARG}" ;;
        L) CAPTION_LANG="${OPTARG}" ;;
        m) MONO_CHANNELS="Y" ;;
        n) REPORT_ONLY="Y" ;;
        N) SEGMENT_SKIPS="${OPTARG}" ;;
        S) SUBS="Y" ;;
        Z) TECHSUBS="Y" ;;
        v) unset FFMPEG_VERBOSE ; DV_VERBOSE=true ;;
        z) DISABLE_COLORED_LOGGING="Y" ;;
        u) UNPACKAGER="Y" ;;
        F) FFMPEG_PATH="${OPTARG}" ;;
        M) MEDIAINFO_PATH="${OPTARG}" ;;
        D) DVRESCUE_PATH="${OPTARG}" ;;
        X) XMLSTARLET_PATH="${OPTARG}" ;;
        x) DVRESCUE_XML="${OPTARG}" ;;
        V) DVRESCUE_TECHSUBS="${OPTARG}" ;;
        C) DVRESCUE_SCC="${OPTARG}" ;;
        3) unset CONDENSE_OPTS ;;
        4) FORCE_SAMPLE_RATE="48000" ;;
        a) ASPECT_RATIO_STRATEGY="${OPTARG}" ;;
        T) SHOW_TABLE="${OPTARG}" ;;
        h) _usage ; exit 0 ;;
        :) echo "Option -${OPTARG} requires an argument" ; _usage ; exit 1 ;;
        *) echo "bad option -${OPTARG}" ; _usage ; exit 1 ;;
    esac
done
shift "$((OPTIND-1))"
DVFILE="${1}"
shift
BASENAME="$(basename "${DVFILE}")"
if [[ -d "${OUTPUTDIR}" ]] ; then
    SIDECAR_DIR="${OUTPUTDIR}"
elif [[ -n "${OUTPUTDIR}" ]] ; then
    _report -w "ERROR: ${OUTPUTDIR} is not a directory."
    exit
else
    SIDECAR_DIR="$(dirname "${DVFILE}")"
fi
case "${EXT}" in
    "mov")
        FORMAT="mov"
        EXTENSION="mov"
        VIDEO_MAP=(-map 0:v:0)
        OPT_OUTPUT+=(-c:a pcm_s16le)
        ;;
    "mkv")
        FORMAT="matroska"
        EXTENSION="mkv"
        VIDEO_MAP=(-map 0:v:0)
        OPT_OUTPUT+=(-c:a pcm_s16le)
        ;;
    "dv")
        FORMAT="rawvideo"
        EXTENSION="dv"
        SUBS="N"
        TECHSUBS="N"
        VIDEO_MAP=(-map 0:v:0)
        ;;
    *)
        _report -w "Error: ${EXT} is an invalid extension option."
        _usage
        exit 1
        ;;
esac
if [[ "${UNPACKAGER}" != "Y" && "${@}" != "" ]] ; then
    _report -w "Error: there are additional unused arguments (${*}). Please reference the DV file last."
    _usage
    exit 0
fi
if [[ "${ASPECT_RATIO_STRATEGY}" == "4" ]] ; then
    CONDENSE_OPTS+=(-a 4)
elif [[ "${ASPECT_RATIO_STRATEGY}" == "9" ]] ; then
    CONDENSE_OPTS+=(-a 9)
elif [[ "${ASPECT_RATIO_STRATEGY}" == "c" ]] ; then
    CONDENSE_OPTS+=(-a c)
fi
_report -v "CONDENSE_OPTS is set to ${CONDENSE_OPTS[*]}"

MATCH_FRAMES="${MATCH_FRAMES%?}"
if [[ -z "${MEDIAINFO_PATH}" ]] ; then
    _get_mediainfo_path
fi
if [[ ! -f "${MEDIAINFO_PATH}" ]] ; then
    _report -d "The mediainfo command-line tool is not found, but is used to verify that the output is well synchronized."
    _report -d "Please install a mediainfo CLI from https://mediaarea.net/en/MediaInfo/Download or provide a path to mediainfo with the -M argument."
fi
if [[ -z "${DVRESCUE_PATH}" ]] ; then
    DVRESCUE_PATH="$(which dvrescue)"
fi
if [[ ! -f "${DVRESCUE_PATH}" ]] ; then
    _report -w "The dvrescue command-line tool is not found."
    exit 1
fi
if [[ -z "${XMLSTARLET_PATH}" ]] ; then
    XMLSTARLET_PATH="$(which xmlstarlet)"
fi
if [[ ! -f "${XMLSTARLET_PATH}" ]] ; then
    _report -w "The xmlstarlet command-line tool is not found."
    exit 1
fi

if [[ -n "${SHOW_TABLE}" ]] ; then
    DVRESCUE_XML="${SHOW_TABLE}"
    if [[ "${DVRESCUE_XML##*.}" != "xml" ]] ; then
        _report -w "In show-table mode, the input should be an xml file."
        exit 1
    fi
    if [[ "${#CONDENSE_OPTS[@]}" = "0" ]] ; then
        _ranges_2_output_table "$(_get_ranges -q)"
    else
        _ranges_2_output_table "$(_condense_ranges "${CONDENSE_OPTS[@]}" "$(_get_ranges -q)")"
    fi
    exit
fi

# if FFMPEG_PATH wasn't provided as an argument then see if one is installed
if [[ -z "${FFMPEG_PATH}" ]] ; then
    _get_ffmpeg_path
fi
# verify that ffmpeg is installed and qualifies
if [[ -z "${FFMPEG_PATH}" ]] ; then
    _report -v "ffmpeg is not found. Please install ffmpeg. Version 4.4 or higher is recommended."
    exit 1
else
    _report -v "Using ${FFMPEG_PATH} for ffmpeg operations."
    # the minimum recommanded version of libavformat, otherwise will use a hack to visualize errors
    LAVF_MAJ_REQ=59
    LAVF_MIN_REQ=5
    LAVF_MIC_REQ=100
    "${FFMPEG_PATH}" -version | grep "libavformat" | head -n 1 | sed 's/[^0-9./]//g' | cut -d "/" -f 1 | while IFS="." read LAVFversion_maj LAVFversion_min LAVFversion_mic ; do
        if ! { \
              [[ ${LAVFversion_maj} -gt ${LAVF_MAJ_REQ} ]] || \
            { [[ ${LAVFversion_maj} -eq ${LAVF_MAJ_REQ} ]] && [[ ${LAVFversion_min} -gt ${LAVF_MIN_REQ} ]]; } || \
            { [[ ${LAVFversion_maj} -eq ${LAVF_MAJ_REQ} ]] && [[ ${LAVFversion_min} -eq ${LAVF_MIN_REQ} ]] && [[ ${LAVFversion_mic} -ge ${LAVF_MIC_REQ} ]]; }; \
           } ; then
            _report -w "FFmpeg's libavformat version  ${LAVF_MAJ_REQ}.${LAVF_MIN_REQ}.${LAVF_MIC_REQ} or greater is recommended and ${FFMPEG_PATH} is running ${LAVFversion_maj}.${LAVFversion_min}.${LAVFversion_mic}."
            _report -w "Please update ffmpeg."
            _report -w "Using this current install of ffmpeg may result in out of sync audio."
        fi
    done
fi

OPT_INPUT=(-y)
OPT_INPUT+=(-nostdin)
OPT_INPUT+=(-hide_banner)
OPT_OUTPUT+=(-c:v:0 copy)

LANG1="$(echo "${LANGUAGES}" | cut -d "," -f1 )"
LANG2="$(echo "${LANGUAGES}" | cut -d "," -f2 )"
LANG3="$(echo "${LANGUAGES}" | cut -d "," -f3 )"
LANG4="$(echo "${LANGUAGES}" | cut -d "," -f4 )"
if [[ -n "${LANG1}" ]] ; then
    OPT_OUTPUT+=(-metadata:s:a:0 language="${LANG1}")
fi
if [[ -n "${LANG2}" ]] ; then
    OPT_OUTPUT+=(-metadata:s:a:1 language="${LANG2}")
fi
if [[ -n "${LANG3}" ]] ; then
    OPT_OUTPUT+=(-metadata:s:a:2 language="${LANG3}")
fi
if [[ -n "${LANG4}" ]] ; then
    OPT_OUTPUT+=(-metadata:s:a:3 language="${LANG4}")
fi

if [[ ! -f "${FFMPEG_PATH}" ]] ; then
    _report -w "Error: ffmpeg is needed but not found."
    exit 1
elif [[ ! -x "${FFMPEG_PATH}" ]] ; then
    _report -w "Error: The ffmpeg needed at ${FFMPEG_PATH} is not executable."
    exit 1
fi

if [[ "${UNPACKAGER}" == "Y" ]] ; then
    OUTPUTNAME="unpackaged_$(uuidgen).dv"
    echo "Unpackaging mode. Unpackaging the input files into ${OUTPUTNAME}."
    for i in "${DVFILE}" "${@}" ; do
        "${FFMPEG_PATH}" -nostdin "${FFMPEG_VERBOSE[@]}" -i "$i" -map 0:v:0 -c copy -f rawvideo - >> "${OUTPUTNAME}"
    done
    exit
fi

OPT_OUTPUT+=(-f "$FORMAT")

unset OUTPUTOPTS
if [[ -z "${DVRESCUE_XML}" ]] ; then
    DVRESCUE_XML="${SIDECAR_DIR}/${BASENAME}.dvrescue.xml"
    if [[ ! -s "${DVRESCUE_XML}" ]] ; then
        DVRESCUE_XML_TEMP="$(_maketemp).xml"
        OUTPUTOPTS+=(--xml-output "${DVRESCUE_XML_TEMP}")
        XML_TO_CHECK="${DVRESCUE_XML_TEMP}"
    else
        XML_TO_CHECK="${DVRESCUE_XML}"
    fi
else
    XML_TO_CHECK="${DVRESCUE_XML}"
fi
if [[ "${TECHSUBS}" = "Y" ]]; then
    if [[ -z "${DVRESCUE_TECHSUBS}" ]] ; then
        DVRESCUE_TECHSUBS="${SIDECAR_DIR}/${BASENAME}.dvrescue.techsubs.vtt"
        if [[ ! -f "${DVRESCUE_TECHSUBS}" ]] ; then
            DVRESCUE_TECHSUBS_TEMP="$(_maketemp).vtt"
            OUTPUTOPTS+=(--webvtt-output "${DVRESCUE_TECHSUBS_TEMP}")
        fi
    fi
fi
if [[ "${SUBS}" = "Y" ]]; then
    if [[ -s "${DVRESCUE_XML}" ]] ; then
        CAPTION_SUMMARY="$("${XMLSTARLET_PATH}" sel -N "d=https://mediaarea.net/dvrescue" -t -m "/d:dvrescue/d:media/d:frames[@captions]" -v @pts -o "-" -v @end_pts -o " captions=" -v @captions -n "${DVRESCUE_XML}")"
        if [[ -z "${CAPTION_SUMMARY}" ]] ; then
            _report -d "A caption track was requested, but the dvrescue xml shows that there were no captions in this DV file."
        fi
    fi
    if [[ -z "${DVRESCUE_SCC}" && ( -n "${CAPTION_SUMMARY}" || ! -s "${DVRESCUE_XML}" ) ]] ; then
        DVRESCUE_SCC="${SIDECAR_DIR}/${BASENAME}.dvrescue.scc"
        if [[ ! -f "${DVRESCUE_SCC}" ]] ; then
            DVRESCUE_SCC_TEMP="$(_maketemp).scc"
            OUTPUTOPTS+=(--cc-format scc)
            OUTPUTOPTS+=(--cc-output "${DVRESCUE_SCC_TEMP}")
        fi
    fi
fi
TOTAL_DVFRAMES_PACKAGED="0"
TOTAL_DVFRAMES_SKIPPED="0"
if [[ -f "${DVFILE}" ]] ; then
    if [[ "${REPORT_ONLY}" = "Y" ]] ; then
        echo -n "Analyzing ${BASENAME}"
    else
        echo -n "Packaging ${BASENAME}"
    fi
    if [[ "${#OUTPUTOPTS[@]}" != 0 ]]; then
        # if dvrescue outputs are needed then let's make them
        echo ", making dvrescue outputs"
        "${DVRESCUE_PATH}" "${DVFILE}" "${OUTPUTOPTS[@]}"
    fi
    ERROR="$("${XMLSTARLET_PATH}" sel -N "d=https://mediaarea.net/dvrescue" -t -m "/d:dvrescue/d:media" -v "@error" "${XML_TO_CHECK}")"
    if [[ -n "${ERROR}" ]] ; then
        echo ". Error: ${BASENAME} (${ERROR})."
        exit 1
    else
        _report -v "No xmlstarlet error"
        # check if the sidecar directory is there
        if [[ ! -d "${SIDECAR_DIR}" ]] ; then
            _report -v "Trying to make a directory at ${SIDECAR_DIR}"
            mkdir -p "${SIDECAR_DIR}"
        fi
        if [[ -s "${DVRESCUE_XML_TEMP}" ]] ; then
            _report -v "Trying to move the temporary xml from ${DVRESCUE_XML_TEMP} to ${DVRESCUE_XML}"
            mv "${DVRESCUE_XML_TEMP}" "${DVRESCUE_XML}"
        fi
        if [[ -s "${DVRESCUE_TECHSUBS_TEMP}" ]] ; then
            _report -v "Trying to move the temporary vtt tfrom ${DVRESCUE_TECHSUBS_TEMP} ${DVRESCUE_TECHSUBS}"
            mv "${DVRESCUE_TECHSUBS_TEMP}" "${DVRESCUE_TECHSUBS}"
        fi
        if [[ -s "${DVRESCUE_SCC_TEMP}" ]] ; then
            _report -v "Trying to move the temporary scc from ${DVRESCUE_SCC_TEMP} to ${DVRESCUE_SCC}"
            mv "${DVRESCUE_SCC_TEMP}" "${DVRESCUE_SCC}"
        fi
    fi
    DV_FRAME_COUNT="$("${XMLSTARLET_PATH}" sel -N "d=https://mediaarea.net/dvrescue" -t -v "sum(/d:dvrescue/d:media[1]/d:frames/@count)" "${DVRESCUE_XML}" 2>/dev/null)"
    _report -v "DV_FRAME_COUNT=(${DV_FRAME_COUNT})"
    SOURCE_FORMAT="$("${XMLSTARLET_PATH}" sel -N "d=https://mediaarea.net/dvrescue" -t -m "/d:dvrescue/d:media[1]" -v "@format" "${DVRESCUE_XML}" 2>/dev/null)"
    _report -v "SOURCE_FORMAT=(${SOURCE_FORMAT})"
    if [[ "${SOURCE_FORMAT}" == "QuickTime" || "${SOURCE_FORMAT}" == "MPEG-4" ]] ; then
        _report -v "Performing test of QuickTime PTS coherency."
        MOV_INPUT_OPT=(-ignore_editlist true)
        MOV_SHOWINFO="$("${FFMPEG_PATH}" -nostdin "${MOV_INPUT_OPT[@]}" -i "${DVFILE}" -vframes 2 -vf showinfo -f null -map 0:v - 2>&1)"
        MOV_PTS_0="$(echo "${MOV_SHOWINFO}" | grep "showinfo.*n:[ ]*0" | grep -o "pts:[ ]*[0-9.]*" | cut -d : -f2 | sed 's/ //g')"
        MOV_PTS_1="$(echo "${MOV_SHOWINFO}" | grep "showinfo.*n:[ ]*1" | grep -o "pts:[ ]*[0-9.]*" | cut -d : -f2 | sed 's/ //g')"
        MOV_PTS_2="$(echo "${MOV_SHOWINFO}" | grep "showinfo.*n:[ ]*2" | grep -o "pts:[ ]*[0-9.]*" | cut -d : -f2 | sed 's/ //g')"
        MOV_PTS_TIME_0="$(echo "${MOV_SHOWINFO}" | grep "showinfo.*n:[ ]*0" | grep -o "pts_time:[ ]*[0-9.]*" | cut -d : -f2 | sed 's/ //g')"
        MOV_PTS_TIME_1="$(echo "${MOV_SHOWINFO}" | grep "showinfo.*n:[ ]*1" | grep -o "pts_time:[ ]*[0-9.]*" | cut -d : -f2 | sed 's/ //g')"
        MOV_PTS_TIME_2="$(echo "${MOV_SHOWINFO}" | grep "showinfo.*n:[ ]*2" | grep -o "pts_time:[ ]*[0-9.]*" | cut -d : -f2 | sed 's/ //g')"
        MOV_FIRST_FRAME_CHECK="$(echo "if ((${MOV_PTS_2} - ${MOV_PTS_0})/2 == ${MOV_PTS_1}) 1 else 0" | bc -l)"
        _report -v "MOV_FIRST_FRAME_CHECK=(${MOV_FIRST_FRAME_CHECK}), MOV_SHOWINFO=(${MOV_SHOWINFO})"
    fi
    _report -v "Trying to present a table of ranges"
    if [[ "${#CONDENSE_OPTS[@]}" = "0" ]] ; then
        _ranges_2_table "$(_get_ranges -q)"
    else
        _ranges_2_table "$(_condense_ranges "${CONDENSE_OPTS[@]}" "$(_get_ranges -q)")"
    fi
    if [[ "$REPORT_ONLY" = "Y" ]] ; then
        exit 0
    fi

    #DVRESCUE_VERSION="$("${XMLSTARLET_PATH}" sel -N "d=https://mediaarea.net/dvrescue" -t -m "d:dvrescue/d:creator[1]" -v "d:program[1]" -o "-" -v "d:version[1]" -o "(" -v "d:library[1]" -o "-" -v "d:library[1]/@version" -o ")" -n "${DVRESCUE_XML}")"
    #MUXER="Lavf${LAVFversion} + ${DVRESCUE_VERSION}"
    _report -d "The results will be written to ${SIDECAR_DIR}"
    SEG_INPUT="1"
    SEG_OUTPUT="1"
    if [[ "${#CONDENSE_OPTS[@]}" = "0" ]] ; then
        OUTPUT_RANGES="$(_get_ranges)"
    else
        OUTPUT_RANGES="$(_condense_ranges "${CONDENSE_OPTS[@]}" "$(_get_ranges)")"
    fi
    OUTPUT_COUNTER="0"
    OUTPUT_TOTAL="$(echo "${OUTPUT_RANGES}" | grep -c "^")"
    echo "${OUTPUT_RANGES}" | while IFS="|" read -r PTS END_PTS FRAME_START FRAME_END TC PKT_POS RDT SIZE VIDEO_RATE CH_SUB AR AUDIO_RATE CH REC_ST RDT_NC TC_NC LAST_FRAME_NO_AUDIO PKT_POS_END PKT_POS_LAST ; do
        ((OUTPUT_COUNTER++))
        if [[ "$(_check_if_in_list "${SEG_INPUT}" "${SEGMENT_SKIPS}")" = "x" ]] ; then
            _report -d "Skipping part ${SEG_INPUT} as requested."
            SKIPPED_DVFRAMES=$((FRAME_END-FRAME_START+1))
            TOTAL_DVFRAMES_SKIPPED=$((TOTAL_DVFRAMES_SKIPPED+SKIPPED_DVFRAMES))
        else
            unset START_TIME METADATA FRAME_COUNT DURATION_SECS DURATION_ARG AUDIO_FILTER APAD SUB_INPUT MOV_PTS_OFFSET MOV_INPUT_RATE_OPT
            unset DV_INPUT AUDIO_INPUTS AUDIO_RESAMPLE_FILTER AUDIO_CONCAT_FILTER AUDIO_RESAMPLE_FILTER_T2 AUDIO_CONCAT_FILTER_T2 CHAPTER_PROCESS OUTPUT_ERROR
            APAD_NOTICE="0"

            # generate output files (this code section is in the table part too)
            APPLIED_PATTERN="$(echo "${OUTPUTPATTERN}" | sed "s|%FILENAME%|${BASENAME%.*}|g;s|%RECDATE%|${RDT:0:4}-${RDT:5:2}-${RDT:8:2}|g;s|%RECTIME%|${RDT:11:2}-${RDT:14:2}-${RDT:17:2}|g;s|%TC%|${TC//[:;]/-}|g;s|%PARTNO%|${SEG_OUTPUT}|g")"
            COLLECTED_OUTPUTS+=(${APPLIED_PATTERN})
            MATCH_NAME_COUNT=0
            for OUTPUT_FILENAME in "${COLLECTED_OUTPUTS[@]}" ; do
                if [[ "${OUTPUT_FILENAME}" = "${APPLIED_PATTERN}" ]]; then
                    (( MATCH_NAME_COUNT++ ))
                fi
            done 
            if [[ "${MATCH_NAME_COUNT}" -gt 1 ]] ; then
                INCREMENT_ADD="-$(echo "${MATCH_NAME_COUNT}-1" | bc -l | awk '{printf "%03d", $0}')"
            else
                INCREMENT_ADD=""
            fi
            OUTPUT_FILE="${SIDECAR_DIR}/${APPLIED_PATTERN}${INCREMENT_ADD}.${EXTENSION}"

            OUTPUT_FILE_BASENAME="$(basename "${OUTPUT_FILE}")"
            #METADATA+=(-metadata "comment=${MUXER}")
            _report -d "### Packaging started: ${OUTPUT_FILE}"
            if [[ "${SOURCE_FORMAT}" == "QuickTime" || "${SOURCE_FORMAT}" == "MPEG-4" ]] ; then
                if [[ "${MOV_FIRST_FRAME_CHECK}" == "0" ]] ; then
                    _report -d "Noting that the first few frames use uneven timestamps [$MOV_PTS_TIME_0,$MOV_PTS_TIME_1,$MOV_PTS_TIME_2]"
                    MOV_PTS_OFFSET="$(echo "(${MOV_PTS_TIME_1} - (1/(${VIDEO_RATE})) )" | bc -l | awk '{printf "%f", $0}')"
                    _report -d "Will apply a pts offset of ${MOV_PTS_OFFSET} to correlate between the timestamps of the encoding and the timestamps of the container."
                fi
                MOV_INPUT_RATE_OPT=(-r "${VIDEO_RATE}") # apply input framerate after pts offset coherency check
            fi
            if [[ "${SOURCE_FORMAT}" == "DV" ]] ; then
                _report -v "Reading from DV stream input at byte range ${PKT_POS}-${PKT_POS_END}"
                DV_INPUT=(-probesize 10M -i "subfile,,start,${PKT_POS},end,${PKT_POS_END:-0},,:${DVFILE}")
            else
                if [[ "${PTS}" = "00:00:00.000000" ]] ; then
                    :
                elif [[ -n "${MOV_PTS_OFFSET}" ]] ; then
                    PTS_OFFED="$(echo "$(_convert_hhmmssmmm2s "${PTS}") + ${MOV_PTS_OFFSET}" | bc -l | awk '{printf "%.9f\n", $0}')"
                    START_TIME=(-ss "${PTS_OFFED}")
                else
                    START_TIME=(-ss "${PTS}")
                fi
                DV_INPUT=("${MOV_INPUT_OPT[@]}" "${MOV_INPUT_RATE_OPT[@]}" "${START_TIME[@]}" -probesize 10M -i "${DVFILE}")
            fi
            FRAME_COUNT="$(echo "${FRAME_END} - ${FRAME_START}" + 1 | bc)"
            DURATION_SECS="$(echo "${FRAME_COUNT}/(${VIDEO_RATE})" | bc -l | awk '{printf "%.9f\n", $0}')"
            DURATION_ARG=(-t "${DURATION_SECS}")
            INPUT_COUNT="1"
            if [[ -n "${TC}" ]] && [[ "${EXTENSION}" != "dv" ]] ; then
                METADATA+=(-metadata "timecode=${TC}")
            fi
            if [[ "${EXTENSION}" != "dv" ]] ; then
                AUDIO_RANGE_SUBLIST="$(_get_ranges -i "${FRAME_START}" -o "${FRAME_END}")"
                _report -v "The audio range sublist (from frame ${FRAME_START} to ${FRAME_END}) is"
                _report -v "${AUDIO_RANGE_SUBLIST}"
                AUDIO_SUBLIST_COUNT="$(echo -n "${AUDIO_RANGE_SUBLIST}" | grep -c '^')"
                if [[ "${AUDIO_SUBLIST_COUNT}" = "1" ]] ; then
                    AUDIO_MAP=(-map 0:a?)
                    if [[ "${LAST_FRAME_NO_AUDIO}" != "0" ]] ; then
                        APAD=",apad=whole_dur=${DURATION_SECS}"
                        _report -d "FYI: Padding a little silence at the end of ${OUTPUT_FILE_BASENAME} since the source ends with frames missing audio."
                        APAD_NOTICE="1"
                    fi

                    AUDIO_SUBFILE_INPUT="subfile,,start,${PKT_POS},end,${PKT_POS_END:-0},,:${DVFILE}"
                    FFMPEG_AUDIO_QUERY_START="$(_check_audio_by_ffmpeg_subfile "${AUDIO_SUBFILE_INPUT[@]}")"
                    if [[ "${CH}" = "0" ]] ; then
                        DVRESCUE_AUDIO_QUERY="0"
                    else
                        DVRESCUE_AUDIO_QUERY="${CH}-${AUDIO_RATE}"
                    fi
                    if [[ "${FFMPEG_AUDIO_QUERY_START}" != "${DVRESCUE_AUDIO_QUERY}" ]] ; then
                        _report -w "ERROR: ffmpeg and dvrescue disagree about the audio characterstics at offset ${PKT_POSa} at ${PTSa}."
                        _report -w "We shall use ffmpeg's analysis on this. (ff:${FFMPEG_AUDIO_QUERY_START} != dvr:${DVRESCUE_AUDIO_QUERY})"
                        _report -w "Consider updating to the latest version of dvrescue and if this error recurs,"
                        _report -w "then consider mentioning this at https://github.com/mipops/dvrescue/issues."
                        CH="$(echo "${FFMPEG_AUDIO_QUERY_START}" | cut -d "-" -f1)"
                    fi
                    _report -v "Prepping a mapping for ${CH} channel input (${MONO_CHANNELS})."
                    if [[ "${CH}" = "2" ]] ; then
                        if [[ "${MONO_CHANNELS}" == "Y" ]] ; then
                            AUDIO_FILTER=(-filter_complex "[0:a:0]aresample=async=1:min_hard_comp=0.01${APAD},channelsplit[l1][r1];[l1]aformat=channel_layouts=mono[c1];[r1]aformat=channel_layouts=mono[c2]")
                            AUDIO_MAP=(-map "[c1]" -map "[c2]")
                        else
                            AUDIO_FILTER=(-filter_complex "[0:a:0]aresample=async=1:min_hard_comp=0.01${APAD}[aud]")
                            AUDIO_MAP=(-map "[aud]")
                        fi
                    elif [[ "${CH}" = "4" ]] ; then
                        if [[ "${MONO_CHANNELS}" == "Y" ]] ; then
                            AUDIO_FILTER=(-filter_complex "[0:a:0]aresample=async=1:min_hard_comp=0.01${APAD},channelsplit[l1][r1];[l1]aformat=channel_layouts=mono[c1];[r1]aformat=channel_layouts=mono[c2];[0:a:1]aresample=async=1:min_hard_comp=0.01${APAD},channelsplit[l2][r2];[l2]aformat=channel_layouts=mono[c3];[r2]aformat=channel_layouts=mono[c4]")
                            AUDIO_MAP=(-map "[c1]" -map "[c2]" -map "[c3]" -map "[c4]")
                        else
                            AUDIO_FILTER=(-filter_complex "[0:a:0]aresample=async=1:min_hard_comp=0.01${APAD}[aud1];[0:a:1]aresample=async=1:min_hard_comp=0.01${APAD}[aud2]")
                            AUDIO_MAP=(-map "[aud1]" -map "[aud2]")
                        fi
                    fi
                else
                    AUDIO_INPUT_COUNT="0"
                    TRACK_2_AUDIO="0"
                    OLDIFS="$IFS"
                    IFS=$'\n'
                    for AUDIO_SUBLIST_LINE in $(echo "${AUDIO_RANGE_SUBLIST}") ; do
                        PTSa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f1)"
                        END_PTSa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f2)"
                        FRAME_STARTa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f3)"
                        FRAME_ENDa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f4)"
                        TCa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f5)"
                        PKT_POSa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f6)"
                        RDTa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f7)"
                        SIZEa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f8)"
                        VIDEO_RATEa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f9)"
                        CH_SUBa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f10)"
                        ARa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f11)"
                        AUDIO_RATEa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f12)"
                        CHa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f13)"
                        REC_STa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f14)"
                        RDT_NCa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f15)"
                        TC_NCa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f16)"
                        LAST_FRAME_NO_AUDIOa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f17)"
                        PKT_POS_ENDa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f18)"
                        PKT_POS_LASTa="$(echo "${AUDIO_SUBLIST_LINE}" | cut -d "|" -f19)"

                        ((AUDIO_INPUT_COUNT++))
                        unset SRa APADa
                        FRAME_COUNTa="$(echo "${FRAME_ENDa} - ${FRAME_STARTa}" + 1 | bc)"
                        DURATION_SECSa="$(echo "${FRAME_COUNTa}/(${VIDEO_RATEa})" | bc -l | awk '{printf "%.9f\n", $0}')"
                        AUDIO_SUBFILE_INPUT="subfile,,start,${PKT_POSa},end,${PKT_POS_ENDa:-0},,:${DVFILE}"
                        AUDIO_INPUTS+=(-probesize 10M -i "${AUDIO_SUBFILE_INPUT}")
                        LAST_FRAME_SUBFILE=(-probesize 10M -i "subfile,,start,${PKT_POS_LASTa},end,${PKT_POS_ENDa:-0},,:${DVFILE}")
                        FFMPEG_AUDIO_QUERY_START="$(_check_audio_by_ffmpeg_subfile "${AUDIO_SUBFILE_INPUT[@]}")"
                        if [[ "${CHa}" = "0" ]] ; then
                            DVRESCUE_AUDIO_QUERY="0"
                        else
                            DVRESCUE_AUDIO_QUERY="${CHa}-${AUDIO_RATEa}"
                        fi
                        if [[ "${FFMPEG_AUDIO_QUERY_START}" != "${DVRESCUE_AUDIO_QUERY}" ]] ; then
                            _report -w "ERROR: ffmpeg and dvrescue disagree about the audio characterstics at offset ${PKT_POSa} at ${PTSa}."
                            _report -w "We shall use ffmpeg's analysis on this. (ff:${FFMPEG_AUDIO_QUERY_START} != dvr:${DVRESCUE_AUDIO_QUERY})"
                            _report -w "Consider updating to the latest version of dvrescue and if this error recurs,"
                            _report -w "then consider mentioning this at https://github.com/mipops/dvrescue/issues."
                            CHa="$(echo "${FFMPEG_AUDIO_QUERY_START}" | cut -d "-" -f1)"
                        fi
                        AUDIO_STREAM_IN="[${AUDIO_INPUT_COUNT}:a:0]"
                        AUDIO_STREAM_OUT="[${AUDIO_INPUT_COUNT}at]"
                        AUDIO_STREAM_IN_T2="[${AUDIO_INPUT_COUNT}:a:1]"
                        AUDIO_STREAM_OUT_T2="[${AUDIO_INPUT_COUNT}at2]"
                        if [[ "${AUDIO_RATEa}" != "48000" ]] ; then
                            SRa="48000:"
                        fi
                        if [[ "${LAST_FRAME_NO_AUDIOa}" != "0" ]] ; then
                            APADa=",apad=whole_dur=${DURATION_SECSa}"
                            _report -d "FYI: Padding a little silence near ${END_PTSa} for ${OUTPUT_FILE_BASENAME} since a source portion ends with frames missing audio (via dvrescue)."
                            APAD_NOTICE="1"
                        else
                            FFMPEG_AUDIO_QUERY_END="$(_check_audio_by_ffmpeg_subfile "${LAST_FRAME_SUBFILE[@]}")"
                            if [[ "${FFMPEG_AUDIO_QUERY_END}" = "0" ]] ; then
                                APADa=",apad=whole_dur=${DURATION_SECSa}"
                                _report -d "FYI: Padding a little silence near ${END_PTSa} for ${OUTPUT_FILE_BASENAME} since a source portion ends with frames missing audio (via ffmpeg)."
                                APAD_NOTICE="1"
                            fi
                        fi
                        AUDIO_CONCAT_FILTER+="${AUDIO_STREAM_OUT}"
                        if [[ "${CHa}" = "4" ]] ; then
                            MAX_DIFF="$(_get_track2_maxdiff "${DVFILE}" "${PKT_POSa}" "${DURATION_SECSa}")"
                            _report -v "Checked track 2 audio levels in ${DVFILE} for ${DURATION_SECSa} from byte ${PKT_POSa}. Maximum sample difference is ${MAX_DIFF}."
                            if [[ "${MAX_DIFF}" != "0.000000" ]] ; then
                                ((TRACK_2_AUDIO++))
                            fi
                            AUDIO_RESAMPLE_FILTER+="${AUDIO_STREAM_IN}aresample=${SRa}async=1:min_hard_comp=0.01${APADa}${AUDIO_STREAM_OUT};"
                            AUDIO_RESAMPLE_FILTER_T2+="${AUDIO_STREAM_IN_T2}aresample=${SRa}async=1:min_hard_comp=0.01${APADa}${AUDIO_STREAM_OUT_T2};"
                        elif [[ "${CHa}" = "0" ]] ; then
                            # since there is no audio, create some
                            AUDIO_RESAMPLE_FILTER+="aevalsrc=channel_layout=stereo:sample_rate=48000:exprs=0|0:duration=${DURATION_SECSa}${AUDIO_STREAM_OUT};"
                            AUDIO_RESAMPLE_FILTER_T2+="aevalsrc=channel_layout=stereo:sample_rate=48000:exprs=0|0:duration=${DURATION_SECSa}${AUDIO_STREAM_OUT_T2};"
                        else
                            AUDIO_RESAMPLE_FILTER+="${AUDIO_STREAM_IN}aresample=${SRa}async=1:min_hard_comp=0.01${APADa}${AUDIO_STREAM_OUT};"
                            AUDIO_RESAMPLE_FILTER_T2+="aevalsrc=channel_layout=stereo:sample_rate=48000:exprs=0|0:duration=${DURATION_SECSa}${AUDIO_STREAM_OUT_T2};"
                        fi
                        AUDIO_CONCAT_FILTER_T2+="${AUDIO_STREAM_OUT_T2}"
                    done
                    IFS="${OLDIFS}"
                    if [[ "${TRACK_2_AUDIO}" = "0" ]] ; then
                        if [[ "${MONO_CHANNELS}" == "Y" ]] ; then
                            AUDIO_FILTER=(-filter_complex "${AUDIO_RESAMPLE_FILTER}${AUDIO_CONCAT_FILTER}concat=n=${AUDIO_INPUT_COUNT}:v=0:a=1,channelsplit[l1][r1];[l1]aformat=channel_layouts=mono[c1];[r1]aformat=channel_layouts=mono[c2]")
                            AUDIO_MAP=(-map "[c1]" -map "[c2]")
                        else
                            AUDIO_FILTER=(-filter_complex "${AUDIO_RESAMPLE_FILTER}${AUDIO_CONCAT_FILTER}concat=n=${AUDIO_INPUT_COUNT}:v=0:a=1[aud]")
                            AUDIO_MAP=(-map "[aud]")
                        fi
                    else
                        _report -v "Adding a second stereo track, as audio was detect in the 3rd or 4th channels of the input dv."
                        if [[ "${MONO_CHANNELS}" == "Y" ]] ; then
                            AUDIO_FILTER=(-filter_complex "${AUDIO_RESAMPLE_FILTER}${AUDIO_RESAMPLE_FILTER_T2}${AUDIO_CONCAT_FILTER}concat=n=${AUDIO_INPUT_COUNT}:v=0:a=1,channelsplit[l1][r1];[l1]aformat=channel_layouts=mono[c1];[r1]aformat=channel_layouts=mono[c2];${AUDIO_CONCAT_FILTER_T2}concat=n=${AUDIO_INPUT_COUNT}:v=0:a=1,channelsplit[l2][r2];[l2]aformat=channel_layouts=mono[c3];[r2]aformat=channel_layouts=mono[c4]")
                            AUDIO_MAP=(-map "[c1]" -map "[c2]" -map "[c3]" -map "[c4]")
                        else
                            AUDIO_FILTER=(-filter_complex "${AUDIO_RESAMPLE_FILTER}${AUDIO_RESAMPLE_FILTER_T2}${AUDIO_CONCAT_FILTER}concat=n=${AUDIO_INPUT_COUNT}:v=0:a=1[aud];${AUDIO_CONCAT_FILTER_T2}concat=n=${AUDIO_INPUT_COUNT}:v=0:a=1[aud_t2]")
                            AUDIO_MAP=(-map "[aud]" -map "[aud_t2]")
                        fi
                    fi
                    INPUT_COUNT=$((INPUT_COUNT + AUDIO_INPUT_COUNT))
                fi
                if [[ "${RDT:0:4}"  =~ ^[0-9]{4} ]] && [[ "${RDT:0:4}" -ge 1995 ]] ; then
                    if [[ "${EXTENSION}" = "mkv" ]] ; then
                        METADATA+=(-metadata "DATE_RECORDED=${RDT}")
                    elif [[ "${EXTENSION}" = "mov" ]] ; then
                        METADATA+=(-metadata "date=${RDT}")
                    fi
                fi
                SUBTITLE_INPUT_COUNT="0"
                if [[ "${SUBS}" = "Y" ]] ; then
                    if [[ -s "${DVRESCUE_SCC}" ]]; then
                        if [[ "${PTS}" != "00:00:00.000000" ]] ; then
                            SUB_INPUT+=(-ss "${PTS}")
                        fi
                        SUB_INPUT+=(-i "${DVRESCUE_SCC}")
                        SUBTITLE_MAP=(-map "${INPUT_COUNT}:s:0")
                        if [[ "${EXT}" = "mov" ]] ; then
                            OPT_OUTPUT+=(-c:s mov_text)
                            OPT_OUTPUT+=(-tag:s:s:"${SUBTITLE_INPUT_COUNT}" tx3g)
                        elif [[ "${EXT}" = "mkv" ]] ; then
                            OPT_OUTPUT+=(-metadata:s:s:"${SUBTITLE_INPUT_COUNT}" "title=Captions")
                            OPT_OUTPUT+=(-c:s ass)
                        fi
                        if [[ -n "${CAPTION_LANG}" ]] ; then
                            OPT_OUTPUT+=(-metadata:s:s:"${SUBTITLE_INPUT_COUNT}" "language=${CAPTION_LANG}")
                        else
                            OPT_OUTPUT+=(-metadata:s:s:"${SUBTITLE_INPUT_COUNT}" "language=und")
                        fi
                        ((INPUT_COUNT++))
                        ((SUBTITLE_INPUT_COUNT++))
                    fi
                fi
                CHAPTER_FFMETADATA="$(_maketemp).ffmetadata"
                _report -v "Writing a chapter track at ${CHAPTER_FFMETADATA}."
                _make_chapter_metadata_file -i "${FRAME_START}" -o "${FRAME_END}" -s "${PTS}" -e "${END_PTS}" > "${CHAPTER_FFMETADATA}"
                if [[ -s "${CHAPTER_FFMETADATA}" ]] ; then
                    CHAPTER_PROCESS=(-i "${CHAPTER_FFMETADATA}")
                    CHAPTER_PROCESS+=(-map_metadata "${INPUT_COUNT}")
                    ((INPUT_COUNT++))
                fi
                if [[ -n "${AR}" ]] ; then
                    METADATA+=(-aspect "${AR}")
                fi
            fi
            MAP_OUTPUT=("${VIDEO_MAP[@]}" "${AUDIO_MAP[@]}" "${SUBTITLE_MAP[@]}")
            if [[ "${SOURCE_FORMAT}" == "DV" ]] ; then
                _report -v "Trying to run: ${FFMPEG_PATH} ${FFMPEG_VERBOSE[@]} ${OPT_INPUT[@]} ${DV_INPUT[@]} ${AUDIO_INPUTS[@]} ${SUB_INPUT[@]} ${CHAPTER_PROCESS[@]} ${AUDIO_FILTER[@]} ${DURATION_ARG[@]} ${OPT_OUTPUT[@]} ${MAP_OUTPUT[@]} ${METADATA[@]} ${OUTPUT_FILE}"
                "${FFMPEG_PATH}" "${FFMPEG_VERBOSE[@]}" "${OPT_INPUT[@]}" "${DV_INPUT[@]}" "${AUDIO_INPUTS[@]}" \
                    "${SUB_INPUT[@]}" "${CHAPTER_PROCESS[@]}" "${AUDIO_FILTER[@]}" "${DURATION_ARG[@]}" "${OPT_OUTPUT[@]}" "${MAP_OUTPUT[@]}" "${METADATA[@]}" "${OUTPUT_FILE}"
            else
                _report -v "Trying to run: ${FFMPEG_PATH} ${FFMPEG_VERBOSE[@]} ${OPT_INPUT[@]} ${DV_INPUT[@]} -map 0:v:0 -c:v:0 copy -f rawvideo - | "${FFMPEG_PATH}" ${FFMPEG_VERBOSE[@]} ${OPT_INPUT[@]} -i - ${SUB_INPUT[@]} ${CHAPTER_PROCESS[@]} ${AUDIO_FILTER[@]} ${DURATION_ARG[@]} ${OPT_OUTPUT[@]} ${MAP_OUTPUT[@]} ${METADATA[@]} ${OUTPUT_FILE}"
                "${FFMPEG_PATH}" "${FFMPEG_VERBOSE[@]}" "${OPT_INPUT[@]}" "${DV_INPUT[@]}" \
                   -map 0:v:0 -c:v:0 copy -f rawvideo - | "${FFMPEG_PATH}" "${FFMPEG_VERBOSE[@]}" "${OPT_INPUT[@]}" -i - \
                    "${SUB_INPUT[@]}" "${CHAPTER_PROCESS[@]}" "${AUDIO_FILTER[@]}" "${DURATION_ARG[@]}" "${OPT_OUTPUT[@]}" "${MAP_OUTPUT[@]}" "${METADATA[@]}" "${OUTPUT_FILE}"
            fi
            if [[ ! -s "${OUTPUT_FILE}" ]] ; then
                OUTPUT_ERROR+=("file-missing")
                OUTPUT_ERROR_NOTE+=("Tried to write an output to ${OUTPUT_FILE} but it's not there. :-/ ")
            else
                if [[ -f "${MEDIAINFO_PATH}" ]] ; then
                    # quick track duration check on the result
                    PACKAGED_DVFRAMES_temp="$(_count_dv_frames "${OUTPUT_FILE}")"
                    PACKAGED_DVFRAMES="${PACKAGED_DVFRAMES_temp//[$'\t\r\n ']}"
                    TOTAL_DVFRAMES_PACKAGED=$((TOTAL_DVFRAMES_PACKAGED+PACKAGED_DVFRAMES))
                    AUD_STREAM_COUNT=($("${MEDIAINFO_PATH}" -f --Output="General;%AudioCount%\n" "${OUTPUT_FILE}" | head -n 1 | sed 's/\r//' | awk '{printf "%s", $0}'))
                    _report -v "AUD_STREAM_COUNT=(${AUD_STREAM_COUNT})"
                    if [[ -n "${AUD_STREAM_COUNT}" ]] ; then
                        VID_DUR=($("${MEDIAINFO_PATH}" -f --Output="Video;%Duration%\n" "${OUTPUT_FILE}" | head -n 1 | sed 's/\r//' | awk '{printf "%s", $0}'))
                        AUD_DUR=($("${MEDIAINFO_PATH}" -f --Output="Audio;%Duration%\n" "${OUTPUT_FILE}" | head -n 1 | sed 's/\r//' | awk '{printf "%s", $0}'))
                        DUR_DIFF=($(echo "${VID_DUR}" - "${AUD_DUR}" | bc | awk '{printf "%f", $0}'))
                        _report -v "VID_DUR=(${VID_DUR}), AUD_DIR=(${AUD_DUR}), DUR_DIFF=(${DUR_DIFF})"
                        if (( $( echo "${DUR_DIFF} >= -033" |bc -l) )) && (( $(echo "${DUR_DIFF} <= 033" |bc -l) )); then
                            _report -v "DUR_DIFF is within an acceptable range."
                        else
                            OUTPUT_ERROR+=("audio-video-duration-mismatch")
                            OUTPUT_ERROR_NOTE+="In ${OUTPUT_FILE_BASENAME} the video track is ${VID_DUR} milliseconds and the audio track is ${AUD_DUR}. These tracks may lose sync. "
                        fi
                    else
                        _report -d "FYI: ${OUTPUT_FILE_BASENAME} has no audio track."
                    fi
                fi
                if [[ -f "${MEDIAINFO_PATH}" ]] && [[ "${PACKAGED_DVFRAMES}" != "${FRAME_COUNT}" ]] ; then
                    OUTPUT_ERROR+=("input-output-framecount-mismatch")
                    OUTPUT_ERROR_NOTE+="${BASENAME} contained ${FRAME_COUNT} DV frames at ${PTS}-${END_PTS} but ${OUTPUT_FILE_BASENAME} contains ${PACKAGED_DVFRAMES} frames of DV. "
                fi
                _report -d "### Done:seg_input=${SEG_INPUT}|seg_output=${SEG_OUTPUT}|output_frames=${PACKAGED_DVFRAMES}|input_frames=${FRAME_COUNT}|audio_fill=${APAD_NOTICE}|output_file=${OUTPUT_FILE}"
            fi
            ((SEG_OUTPUT++))
            if [[ "${OUTPUT_ERROR[@]}" != "" ]] ; then
                _report -w "### Packaging error: ${OUTPUT_ERROR[*]}"
                _report -w "### Packaging error note: ${OUTPUT_ERROR_NOTE[*]}"
            fi
            _report -d "### Packaging finished: ${OUTPUT_FILE}"
        fi
        ((SEG_INPUT++))
        if [[ "${OUTPUT_COUNTER}" == "${OUTPUT_TOTAL}" ]] ; then
            if [[ -f "${MEDIAINFO_PATH}" ]] && [[ "$((TOTAL_DVFRAMES_PACKAGED+TOTAL_DVFRAMES_SKIPPED))" != "${DV_FRAME_COUNT}" ]] ; then
                _report -w "ERROR: ${BASENAME} contained ${DV_FRAME_COUNT} DV frames, but the outputs contain ${TOTAL_DVFRAMES_PACKAGED} frames of DV and ${TOTAL_DVFRAMES_SKIPPED} were skipped"
            fi
        fi
    done
else
    echo "${BASENAME} is not a file, skipping."
fi
