. "$BST_LIB" # BST-TIMEOUT: 300 # 85 cases over ~40 execs of a wasm module, each a fresh # # instantiation (0.17s for the same 85 natively, which is # # why the exec count and not the arithmetic sets the bound). # # 300 is the value the ticket gate and the nightly already # # pass, so it costs them nothing, and it is the net for a # # bare `brintos-selftest` whose 60s default would leave too # # little margin over a figure measured on a loaded host. # mpeg2dec 0.5.1 / libmpeg2 (poky recipes-multimedia/mpeg2dec) -- the MPEG-1 and # MPEG-2 video decoder: libmpeg2.a, libmpeg2convert.a, two headers under # /usr/include/mpeg2dec, and the three programs `mpeg2dec`, `extract_mpeg2` and # `corrupt_mpeg2`. Every output mode this suite uses writes to a file or a pipe # and none opens a display, so the whole of it runs offline with no framebuffer, # no X server and no window system. # # THE ORACLE IS A STORED REFERENCE DECODE, AND IT RESTS ON A STRUCTURAL FACT # RATHER THAN A MEASUREMENT. Two neighbouring codec suites (57-libvorbis, # 57-speexdsp) refuse a stored cross-machine digest and are right to: their # decoders are floating-point, so a last-ulp disagreement between two libm # implementations reaches the output. libmpeg2 is a different case and the # difference is categorical -- THERE IS NO FLOATING POINT IN THE DECODER AT ALL. # `grep -lE 'float|double' libmpeg2/*.c` returns nothing across the whole # library: the IDCT is the classic integer transform (W1..W7 = 2841..565 with # fixed shifts), motion compensation is integer averaging, and the bitstream # reader is integer. Exact integer arithmetic gives the same answer on every # conforming C implementation, so a byte-exact cross-architecture reference is # not a hope about rounding, it is what the code computes. Measured anyway: the # same source at gcc 9.5 -O2 and gcc 9.5 -O0 produces BYTE-IDENTICAL output for # all four fixtures. # # `-c` IS ON EVERY DECODE BELOW AND IT IS LOAD-BEARING. It calls mpeg2_accel(0), # which selects the pure-C IDCT and motion compensation instead of whatever SIMD # the host advertises. libmpeg2's MMX/SSE2 kernels are NOT bit-identical to its C # ones -- measured on the build host that generated these fixtures (SSE2/SSSE3/ # SSE4.2/AVX2): the accelerated decode DIFFERS from the C decode for both the # MPEG-1 and the MPEG-2 fixture. A reference generated without -c would therefore # have encoded which SIMD the generating host happened to have, and this target, # which has none, could never have matched it. On wasm32 there is no accelerated # path to select, so -c changes nothing here -- which is exactly what # mpeg2dec/accel-c-agrees asserts, so that the day an accelerated path does # appear, this suite says so instead of going quietly red on every byte # comparison at once. # # WHAT THE FIXTURES ARE. All four are synthetic, built by src/mpeg2dec_mkfixtures.py # and encoded with ffmpeg 6.1.2 at -g 4 -bf 2 -qscale:v 4 -threads 1; that file # states why none of those is a default. The source is eight 128x96 YUV420p # frames generated by integer arithmetic on the frame index -- a static vertical # ramp, a bright square translating by (+3,+2) px/frame, and a chroma-only bar # translating by (-5,0) px/frame -- and all four fixtures carry the SAME eight # frames, so any difference between their decodes is a difference in the # container or the standard, never in the content. # # mpeg2dec-mp2v.m2v MPEG-2 video elementary stream <- the ticket's criterion # mpeg2dec-mp1v.m1v MPEG-1 video elementary stream # mpeg2dec-ps.mpg MPEG-2 program stream (mp2v remuxed, -c copy) # mpeg2dec-ts.ts MPEG-2 transport stream (mp2v remuxed, -c copy) # # EACH EXISTS FOR A CODE PATH THE OTHERS DO NOT REACH. # # * mp2v is the plain MPEG-2 case and the one the ticket names. # * mp1v is the same eight frames as MPEG-1. The two standards are not a # cosmetic difference in libmpeg2 -- MPEG-1 has no picture_coding_extension, # no field/frame DCT selection and a different default intra matrix -- and # the decodes DIFFER, so an MPEG-2-only regression is invisible without it. # * ps drives the program-stream demultiplexer, both mpeg2dec's internal one # (-s) and the standalone `extract_mpeg2`, the second program this ticket # ships. # * ts drives the transport-stream demultiplexer, which is separate code from # the program-stream one: a 188-byte packet layer with a PID filter, against # -s's variable-length PES-in-pack layer. # # BECAUSE ps AND ts CARRY THE mp2v ELEMENTARY STREAM UNMODIFIED (-c copy, not a # re-encode), THE DEMUXERS GET AN EXACT ORACLE RATHER THAN A PLAUSIBLE ONE. The # suite asserts that extract_mpeg2 reproduces mpeg2dec-mp2v.m2v BYTE FOR BYTE out # of each container, and that decoding through either demuxer gives the same # picture stream as decoding the elementary stream directly. A demuxer that # dropped or duplicated a packet would still produce a decodable stream; it could # not produce that one. # # THE FIXTURES CARRY A SEQUENCE_END_CODE AND THAT IS DELIBERATE. ffmpeg's raw # video muxers do not write one, and without it libmpeg2 releases only 6 of the 8 # encoded pictures: a picture is emitted once the NEXT start code proves it # complete, and with -bf 2 the final pictures sit in the reorder buffer with # nothing after them to flush it. That is not a defect -- it is what an # unterminated stream means -- but a fixture that silently dropped its last two # frames would never compare the two with the most accumulated motion, which are # exactly the ones a motion-compensation fault shows up in. Both halves are # pinned (mpeg2dec/frames-terminated, mpeg2dec/frames-unterminated), the second # by removing the four bytes on target rather than shipping a fifth fixture, so a # reader who meets the 6-frame behaviour elsewhere does not file it against us. require mpeg2dec mpeg2dec/present tmp=${TMPDIR:-/tmp}/bst-mpeg2dec.$$ mkdir -p "$tmp" 2>/dev/null size() { wc -c < "$1" 2>/dev/null | tr -d ' '; } md5of() { md5sum "$1" 2>/dev/null | cut -d' ' -f1; } lines() { wc -l < "$1" 2>/dev/null | tr -d ' '; } have_md5=0; command -v md5sum >/dev/null 2>&1 && have_md5=1 D=$BST_DATA # dec : decode with the C path, banner and timing to /dev/null. dec() { _o=$1; shift; mpeg2dec -c "$@" >"$_o" 2>/dev/null; } # --------------------------------------------------------------- what shipped --- check mpeg2dec/extract-present test -x /usr/bin/extract_mpeg2 check mpeg2dec/corrupt-present test -x /usr/bin/corrupt_mpeg2 check mpeg2dec/lib-static test -f /usr/lib/libmpeg2.a check mpeg2dec/libconvert-static test -f /usr/lib/libmpeg2convert.a check mpeg2dec/header-mpeg2 test -f /usr/include/mpeg2dec/mpeg2.h check mpeg2dec/header-convert test -f /usr/include/mpeg2dec/mpeg2convert.h check mpeg2dec/pkgconfig test -f /usr/lib/pkgconfig/libmpeg2.pc # Shape, not absence: this arm converts to shared libraries per recipe # (BRINTOS-1740), so a .so here is a conversion, not a policy breach. bst_lib_shape mpeg2dec/static-only "/usr/lib/libmpeg2*.so*" b=$(mpeg2dec -o nosuchdriver /dev/null 2>&1) case "$b" in *"libmpeg2-0.5.1"*) bst_ok mpeg2dec/banner ;; *) bst_notok mpeg2dec/banner "$(_bst_1line "$b")" ;; esac # ------------------------------------------------------------ the driver table --- # These three are the only cases that can see the recipe's --disable-sdl and the # absent x11 PACKAGECONFIG, and every decode case below would still pass with # them red. video_out.c builds its table in #ifdef order and mpeg2dec's option # loop ends with `if (output_open == NULL) output_open = drivers[0].open;`, so an # x11 or SDL driver compiled in would take over the default for a bare # invocation -- on an image with no display, that is a decoder that cannot decode # without being told -o. With both out, drivers[0] is "null". # # Unlike a52dec's OSS backend (BRINTOS-788), neither is enabled from a host-triple # match: --disable-sdl is passed by poky's own recipe and x11 comes from # PACKAGECONFIG, which is empty because DISTRO_FEATURES carries no x11. So this # is a weaker hazard than liba52's -- but it is the same shape, it is asserted # the same way, and a DISTRO_FEATURES change is exactly the kind of edit that # would turn it on without anyone editing this recipe. case "$b" in *" x11"*|*" xv"*) bst_notok mpeg2dec/no-x11-driver "x11/xv driver compiled in" ;; *) bst_ok mpeg2dec/no-x11-driver ;; esac case "$b" in *" sdl"*) bst_notok mpeg2dec/no-sdl-driver "sdl driver compiled in" ;; *) bst_ok mpeg2dec/no-sdl-driver ;; esac # The $ anchor is not decoration. print_usage writes "-h display help and # available video output modeS" BEFORE the "-o video output mode" line it means, # so an unanchored match takes the -h line and getline returns the -s line -- # which is what the first cut of this case did, reporting the default driver as # "-suseprogramstreamdemultiplexer". Only the -o line ends at "mode". first=$(printf '%s\n' "$b" | awk '/video output mode$/{getline; gsub(/[ \t]/,"",$0); print; exit}') check_eq mpeg2dec/default-driver-is-null null "$first" # ------------------------------------------------------------------ payloads --- # Pinned BEFORE anything is decoded. Without this a later mismatch has two # indistinguishable causes -- the decoder changed, or the payload did -- and the # wrong one gets reported. pin() { # pin if [ "$have_md5" -eq 1 ]; then check_eq "$1" "$2" "$(md5of "$3")" else bst_skip "$1" "no md5sum on this image"; fi } pin mpeg2dec/fixture-mp2v-digest 6361e7fdf50c7b47989a95d0a6eba32c "$D/mpeg2dec-mp2v.m2v" pin mpeg2dec/fixture-mp1v-digest aca5019bbb2d4a5c86c5105d361cd94d "$D/mpeg2dec-mp1v.m1v" pin mpeg2dec/fixture-ps-digest 847692f74bcdd53892b0b972f4f79530 "$D/mpeg2dec-ps.mpg" pin mpeg2dec/fixture-ts-digest 8c0e0161ae97c22bec34783ba64808ab "$D/mpeg2dec-ts.ts" pin mpeg2dec/reference-mp2v-digest b5c2c675f551de2a19893d0be0762928 "$D/mpeg2dec-mp2v.ref.pgm" pin mpeg2dec/reference-mp1v-digest 1d47b1b4b75146b6a997817cb34b073a "$D/mpeg2dec-mp1v.ref.pgm" pin mpeg2dec/reference-ps-digest b5c2c675f551de2a19893d0be0762928 "$D/mpeg2dec-ps.ref.pgm" pin mpeg2dec/reference-ts-digest b5c2c675f551de2a19893d0be0762928 "$D/mpeg2dec-ts.ref.pgm" pin mpeg2dec/reference-es-digest 6361e7fdf50c7b47989a95d0a6eba32c "$D/mpeg2dec-ps.ref.m2v" for f in mpeg2dec-mp2v.m2v mpeg2dec-mp1v.m1v mpeg2dec-ps.mpg mpeg2dec-ts.ts \ mpeg2dec-mp2v.ref.pgm mpeg2dec-mp1v.ref.pgm mpeg2dec-ps.ref.pgm \ mpeg2dec-ts.ref.pgm mpeg2dec-mp2v.ref.md5 mpeg2dec-mp1v.ref.md5 \ mpeg2dec-ps.ref.md5 mpeg2dec-ts.ref.md5 mpeg2dec-ps.ref.m2v \ mpeg2dec-ts.ref.m2v; do if [ ! -f "$D/$f" ]; then bst_notok mpeg2dec/payloads "missing $D/$f -- remaining cases not run" rm -rf "$tmp"; exit 0 fi done # ------------------------------------------------- the byte-exact decodes --- # The ticket's own criterion, for each fixture in turn: decode to raw frames on # target and compare byte-exactly against what the same version produces on # x86-64. `-o pgmpipe` writes the decoded planes to stdout as a concatenated # P5 stream (Y over a side-by-side U/V half-plane, so 2*chroma_width wide and # height+chroma_height tall); the banner and the timing line go to stderr, so # stdout is frame bytes and nothing else -- 8 x (15-byte header + 128*144) = # 147576 bytes for every one of these fixtures. # # Three graded cases per fixture, and the split is what makes a red readable: # -decode the decode ran at all (rc 0) # -bytes the whole output is byte-identical to the reference <- the criterion # -md5 the per-frame digests match, which LOCALISES a mismatch to a frame # `-o md5` is libmpeg2's own driver: it MD5s exactly the bytes the pgm writer # would have emitted, one line per frame, so -md5 is the same assertion as -bytes # cut per picture. A red on -bytes with -md5 green would mean the frames are each # correct but the stream framing is not; the reverse localises which picture # diverged. Both are cheap; neither is redundant. for spec in "mp2v mpeg2dec-mp2v.m2v" \ "mp1v mpeg2dec-mp1v.m1v" \ "ps mpeg2dec-ps.mpg -s" \ "ts mpeg2dec-ts.ts -t 0x100"; do # shellcheck disable=SC2086 set -- $spec n=$1; f=$2; shift 2 dec "$tmp/$n.pgm" "$@" -o pgmpipe "$D/$f"; rc=$? check_eq mpeg2dec/$n-decode 0 "$rc" check mpeg2dec/$n-bytes cmp -s "$tmp/$n.pgm" "$D/mpeg2dec-$n.ref.pgm" dec "$tmp/$n.md5" "$@" -o md5 "$D/$f" check mpeg2dec/$n-md5 cmp -s "$tmp/$n.md5" "$D/mpeg2dec-$n.ref.md5" check_eq mpeg2dec/$n-frames 8 "$(lines "$tmp/$n.md5")" check_eq mpeg2dec/$n-size 147576 "$(size "$tmp/$n.pgm")" done # The two multiplexed fixtures carry the mp2v elementary stream unmodified, so # their decodes must equal the mp2v decode EXACTLY. This is the case that # separates a demuxer fault from a decoder fault: if -bytes is red for ps but # green for mp2v, the demuxer is what changed. check mpeg2dec/ps-decode-equals-mp2v cmp -s "$tmp/ps.pgm" "$tmp/mp2v.pgm" check mpeg2dec/ts-decode-equals-mp2v cmp -s "$tmp/ts.pgm" "$tmp/mp2v.pgm" # MPEG-1 and MPEG-2 decodes of the SAME source frames must NOT be equal. If they # ever are, the mp1v fixture has stopped testing anything and the suite is a # case lighter than it reads -- the failure mode a passing suite cannot show. if cmp -s "$tmp/mp1v.pgm" "$tmp/mp2v.pgm"; then bst_notok mpeg2dec/mp1v-distinct "MPEG-1 and MPEG-2 decodes are identical -- the mp1v fixture is not exercising the MPEG-1 path" else bst_ok mpeg2dec/mp1v-distinct; fi # -------------------------------------------------------- extract_mpeg2 --- # The second program the ticket names. Its oracle is exact rather than # approximate: ps and ts were remuxed from mpeg2dec-mp2v.m2v with -c copy, so a # correct demultiplexer returns that file byte for byte. extract_mpeg2 "$D/mpeg2dec-ps.mpg" >"$tmp/ps.es" 2>/dev/null check_eq mpeg2dec/extract-ps-rc 0 "$?" check mpeg2dec/extract-ps-bytes cmp -s "$tmp/ps.es" "$D/mpeg2dec-ps.ref.m2v" check mpeg2dec/extract-ps-roundtrip cmp -s "$tmp/ps.es" "$D/mpeg2dec-mp2v.m2v" extract_mpeg2 -t 0x100 "$D/mpeg2dec-ts.ts" >"$tmp/ts.es" 2>/dev/null check_eq mpeg2dec/extract-ts-rc 0 "$?" check mpeg2dec/extract-ts-bytes cmp -s "$tmp/ts.es" "$D/mpeg2dec-ts.ref.m2v" check mpeg2dec/extract-ts-roundtrip cmp -s "$tmp/ts.es" "$D/mpeg2dec-mp2v.m2v" # extract then decode: the two programs composed, which is how anyone actually # uses them. Byte-identical to the direct decode or the composition is broken. dec "$tmp/ps.es.pgm" -o pgmpipe "$tmp/ps.es" check mpeg2dec/extract-then-decode cmp -s "$tmp/ps.es.pgm" "$D/mpeg2dec-mp2v.ref.pgm" # extract_mpeg2 reads stdin when given no file, which is the pipeline form. ( extract_mpeg2 < "$D/mpeg2dec-ps.mpg" >"$tmp/ps.stdin.es" 2>/dev/null ) check mpeg2dec/extract-stdin cmp -s "$tmp/ps.stdin.es" "$D/mpeg2dec-mp2v.m2v" # ------------------------------------------------------- stream structure --- # What the decoder says it saw. These pin that the fixtures still exercise the # paths the header comment claims they do: a suite whose fixtures quietly became # all-intra would keep every byte comparison green while testing a third of the # decoder. v2=$(mpeg2dec -c -v -o null "$D/mpeg2dec-mp2v.m2v" 2>&1) v1=$(mpeg2dec -c -v -o null "$D/mpeg2dec-mp1v.m1v" 2>&1) case "$v2" in *"SEQUENCE MPEG2"*) bst_ok mpeg2dec/mp2v-is-mpeg2 ;; *) bst_notok mpeg2dec/mp2v-is-mpeg2 "$(_bst_1line "$v2")" ;; esac case "$v1" in *"SEQUENCE MPEG2"*) bst_notok mpeg2dec/mp1v-is-mpeg1 "MPEG-1 fixture reports MPEG2" ;; *"SEQUENCE"*) bst_ok mpeg2dec/mp1v-is-mpeg1 ;; *) bst_notok mpeg2dec/mp1v-is-mpeg1 "$(_bst_1line "$v1")" ;; esac case "$v2" in *"128x96"*) bst_ok mpeg2dec/mp2v-geometry ;; *) bst_notok mpeg2dec/mp2v-geometry "$(_bst_1line "$v2")" ;; esac # -g 4 -bf 2 over 8 frames is exactly 2 I, 2 P and 4 B pictures. The B count is # the one that matters: without bidirectional pictures the reorder buffer and # the backward-prediction path are never entered, and that is half of libmpeg2. pics() { printf '%s\n' "$v2" | grep -c "PICTURE $1"; } check_eq mpeg2dec/mp2v-pictures-i 2 "$(pics I)" check_eq mpeg2dec/mp2v-pictures-p 2 "$(pics P)" check_eq mpeg2dec/mp2v-pictures-b 4 "$(pics B)" # ---------------------------------------------------- the flush behaviour --- # Both halves of the sequence_end_code property, so a reader who meets the # 6-frame form elsewhere can see it is upstream's design and not our port. The # unterminated stream is derived here rather than shipped as a fifth fixture. check_eq mpeg2dec/frames-terminated 8 "$(lines "$tmp/mp2v.md5")" head -c $(( $(size "$D/mpeg2dec-mp2v.m2v") - 4 )) "$D/mpeg2dec-mp2v.m2v" > "$tmp/unterm.m2v" 2>/dev/null dec "$tmp/unterm.md5" -o md5 "$tmp/unterm.m2v" check_eq mpeg2dec/frames-unterminated 6 "$(lines "$tmp/unterm.md5")" # and the 6 it does emit are the first 6 of the terminated decode, unchanged -- # the pictures are withheld, not corrupted. head -n 6 "$D/mpeg2dec-mp2v.ref.md5" > "$tmp/first6.md5" check mpeg2dec/unterminated-prefix cmp -s "$tmp/unterm.md5" "$tmp/first6.md5" # ----------------------------------------------------------- the -c knob --- # On wasm32 there is no accelerated path, so -c must be a no-op. If this ever # goes red an accelerated path has appeared, and every byte comparison above # would go red at the same time; this case is what says WHY. mpeg2dec -o md5 "$D/mpeg2dec-mp2v.m2v" >"$tmp/noc.md5" 2>/dev/null check mpeg2dec/accel-c-agrees cmp -s "$tmp/noc.md5" "$tmp/mp2v.md5" # ------------------------------------------------------- other output modes --- # The null drivers and the file-per-frame pgm writer, which is the mode a user # reaches for first. `-o pgm` writes .pgm into the CURRENT directory, so it is # run from $tmp; that it writes 8 files of the expected size is the assertion, # and 0.pgm must equal the first frame of the pgmpipe stream. for m in null nullslice nullskip nullrgb16 nullrgb32; do check mpeg2dec/mode-$m mpeg2dec -c -o $m "$D/mpeg2dec-mp2v.m2v" done ( cd "$tmp" && mkdir -p pgmdir && cd pgmdir && mpeg2dec -c -o pgm "$D/mpeg2dec-mp2v.m2v" >/dev/null 2>&1 ) check_eq mpeg2dec/pgm-file-count 8 "$(ls "$tmp/pgmdir" 2>/dev/null | wc -l | tr -d ' ')" head -c 18447 "$D/mpeg2dec-mp2v.ref.pgm" > "$tmp/frame0.pgm" check mpeg2dec/pgm-first-frame cmp -s "$tmp/pgmdir/0.pgm" "$tmp/frame0.pgm" # ------------------------------------------------------------- corrupt_mpeg2 --- # The third program in the package. Its own RNG (fastrand) is seeded explicitly # with -l, so it is deterministic WITHIN a machine -- which is what is asserted. # No cross-machine byte comparison is made: randbyte_init takes the probability # as a double, and a float-to-threshold conversion is the one place in this # package where two architectures could legitimately differ. What matters for the # port is that the tool runs and that the decoder survives what it produces. # # TWO THINGS ABOUT -l THAT ARE NOT IN THE USAGE LINE. It parses its argument with # sscanf("%08x%08x%08x%08x"), so the seed is 32 HEX DIGITS and nothing shorter -- # `-l 1` matches one conversion of four, falls into print_usage, and exits 1 with # an empty output file. And passing -l at all is what SUPPRESSES a side effect: # with neither -l nor -s, main() does fopen("seed", "wt") in the CURRENT # directory, so a suite that omitted the seed would litter the guest's cwd. SEED=0123456789abcdef0123456789abcdef corrupt_mpeg2 -l $SEED -r 0.01 "$D/mpeg2dec-mp2v.m2v" >"$tmp/c1.m2v" 2>/dev/null check_eq mpeg2dec/corrupt-rc 0 "$?" check mpeg2dec/corrupt-output-nonempty test -s "$tmp/c1.m2v" check_eq mpeg2dec/corrupt-size-preserved "$(size "$D/mpeg2dec-mp2v.m2v")" "$(size "$tmp/c1.m2v")" corrupt_mpeg2 -l $SEED -r 0.01 "$D/mpeg2dec-mp2v.m2v" >"$tmp/c2.m2v" 2>/dev/null check mpeg2dec/corrupt-deterministic cmp -s "$tmp/c1.m2v" "$tmp/c2.m2v" # ...and it must actually have corrupted something, or every case below it is # asserting that the decoder survives an untouched stream. if cmp -s "$tmp/c1.m2v" "$D/mpeg2dec-mp2v.m2v"; then bst_notok mpeg2dec/corrupt-changed-bytes "output is byte-identical to the input -- nothing was corrupted" else bst_ok mpeg2dec/corrupt-changed-bytes; fi check mpeg2dec/corrupt-no-stray-seed test ! -f seed # ------------------------------------------------------------- robustness --- # A decoder that is fed damage must terminate and say so, not hang or fault. The # exit status is deliberately not asserted to a single value: libmpeg2 is # designed to resynchronise at the next start code, so a corrupt stream # legitimately decodes to completion. What is asserted is that the process ENDS # and that the suite is still running afterwards. mpeg2dec -c -o null "$tmp/c1.m2v" >/dev/null 2>&1; rc=$? if [ "$rc" -lt 128 ]; then bst_ok mpeg2dec/corrupt-survives else bst_notok mpeg2dec/corrupt-survives "died on signal $(( rc - 128 ))"; fi head -c 800 "$D/mpeg2dec-mp2v.m2v" > "$tmp/trunc.m2v" mpeg2dec -c -o null "$tmp/trunc.m2v" >/dev/null 2>&1; rc=$? if [ "$rc" -lt 128 ]; then bst_ok mpeg2dec/truncated-survives else bst_notok mpeg2dec/truncated-survives "died on signal $(( rc - 128 ))"; fi dd if=/dev/zero of="$tmp/zero.bin" bs=1024 count=8 2>/dev/null mpeg2dec -c -o null "$tmp/zero.bin" >/dev/null 2>&1; rc=$? if [ "$rc" -lt 128 ]; then bst_ok mpeg2dec/garbage-survives else bst_notok mpeg2dec/garbage-survives "died on signal $(( rc - 128 ))"; fi # Decoding an ELEMENTARY stream with -s (asking for a program-stream demuxer) # finds no pack header and decodes nothing. It must still exit cleanly. mpeg2dec -c -s -o md5 "$D/mpeg2dec-mp2v.m2v" >"$tmp/wrongdemux.md5" 2>/dev/null; rc=$? if [ "$rc" -lt 128 ]; then bst_ok mpeg2dec/wrong-demuxer-survives else bst_notok mpeg2dec/wrong-demuxer-survives "died on signal $(( rc - 128 ))"; fi check_eq mpeg2dec/wrong-demuxer-no-frames 0 "$(lines "$tmp/wrongdemux.md5")" # ---------------------------------------------------------------- negatives --- e=$(mpeg2dec -c -o null "$tmp/nosuchfile" 2>&1 >/dev/null); rc=$? check_eq mpeg2dec/missing-file-rc 1 "$rc" case "$e" in *"could not open file"*) bst_ok mpeg2dec/missing-file-diagnostic ;; *) bst_notok mpeg2dec/missing-file-diagnostic "$(_bst_1line "$e")" ;; esac e=$(mpeg2dec -o nosuchdriver /dev/null 2>&1 >/dev/null); rc=$? check_eq mpeg2dec/bad-driver-rc 1 "$rc" case "$e" in *"Invalid video driver"*) bst_ok mpeg2dec/bad-driver-diagnostic ;; *) bst_notok mpeg2dec/bad-driver-diagnostic "$(_bst_1line "$e")" ;; esac e=$(extract_mpeg2 "$tmp/nosuchfile" 2>&1 >/dev/null); rc=$? check_eq mpeg2dec/extract-missing-file-rc 1 "$rc" rm -rf "$tmp"