1. #!/bin/bash
  2. # @(#)$Header: /home/mythtv/mythtvrep/scripts/mythnuv2mkv.sh,v 1.61 2010/10/09 21:06:19 mythtv Exp $
  3. # Auric 2007/07/10 http://web.aanet.com.au/auric/
  4. # source the config file
  5. [ -f $(dirname "$0")/mythnuv2mkv.cfg ] && . $(dirname "$0")/mythnuv2mkv.cfg
  6.  
  7. ##########################################################################################################
  8. #
  9. # Convert MythRecording & MythVideo nuv or mpg files to mkv mp4 or avi.
  10. #
  11. ######### Vars you may want to set for your environment, put them in mythnuv2mkv.cfg along with this script ##
  12.  
  13. # Default aspect for Myth Recording mpg files. It will try to work it out but if it can't will use this.
  14. readonly DEFAULTMPEG2ASPECT="${DEFAULTMPEG2ASPECT-NA}" # 4:3 or 16:9
  15. # Log directory
  16. readonly LOGBASEDIR="${LOGBASEDIR-/var/tmp}" # Don't use a directory with spaces in it's name
  17. # Number of errors reported by mplayer allowed in the transcoded file
  18. readonly MPLAYER_ERROR_COUNT="${MPLAYER_ERROR_COUNT-8}"
  19. # Path to your mysql.txt file
  20. readonly MYSQLTXT="${MYSQLTXT-}"
  21. # What to separate title, subtitle etc. with
  22. readonly SEP="${SEP-,}"
  23. # What (if at all) to replace spaces with
  24. readonly TR="${TR-_}"
  25. # printf(episode_number)
  26. readonly EPISODE_FORMAT="${EPISODE_FORMAT-E%02d}"
  27. # printf(formatted_episode, season_number)
  28. readonly SEASON_FORMAT="${SEASON_FORMAT-S%2\$02d%1\$s }"
  29. # printf(title, formatted_season_episode)
  30. readonly TITLE_FORMAT="${TITLE_FORMAT-%s %s}"
  31. # printf(filename, date)
  32. readonly DATE_FORMAT="${DATE_FORMAT-%s [%s]}"
  33. # RegEx for matching season/episode numbers
  34. readonly EPISODE_RE="${EPISODE_RE-^S[0-9]+E[0-9]+ $}"
  35. # Chapter marks every X minutes
  36. CHAPTERDURATION="${CHAPTERDURATION-0}"
  37. # Crop input
  38. CROP="${CROP-ON}" # ON | OFF, can also change with --crop argument
  39. CROPSIZE="${CROPSIZE-8}"
  40. # Delete recording after successful transcode. Only for transcode out of MythRecording. (Actually just sets to high priority autoexpire.)
  41. DELETEREC="${DELETEREC-OFF}" # ON | OFF, can also change with --deleterec argument
  42. # Include denoise filter
  43. DENOISE="${DENOISE-OFF}" # ON | OFF, can also change with --denoise argument
  44. # Include deblock filter
  45. DEBLOCK="${DEBLOCK-OFF}" # ON | OFF, can also change with --deblock argument
  46. # Include deinterlace filter.
  47. # SOURCENAME is ON for that source. Can have multiple. e.g. DEINTERLACE="Cabel,FTA1"
  48. DEINTERLACE="${DEINTERLACE-ON}" # ON | OFF | SOURCENAME,SOURCENAME can also change with --deinterlace argument.
  49. # Include inverse Telecine filter (Experimental. Can someone from NTSC/ATSC land try this?).
  50. # invtelecine filter is never added if deinterlace has been added.
  51. INVTELECINE="${INVTELECINE-OFF}" # ON | OFF, can also change with --invtelecine argument.
  52. # number passes
  53. PASS="${PASS-two}" # one | two, can also change with --pass argument
  54. # number of threads. Only used by lavc and xvid (x.264 auto calculates threads)
  55. THREADS="${THREADS-1}"
  56. # avi encoder lavc or xvid
  57. AVIVID="${AVIVID-lavc}" # lavc | xvid, can also change with --contype=avi,xvid argument
  58. # container
  59. CONTYPE="${CONTYPE-mkv}" # mkv | mp4 | avi, can also change with --contype argument or name of script.
  60. # mkv audio encoder aac or ogg
  61. MKVAUD="${MKVAUD-aac}" # aac | ogg, can also change with --contype=mkv,ogg argument
  62. # audio tracks with, optionally, their language code, in the order they are to be added to the resulting file
  63. # language codes and multiple tracks only supported in mp4 and mkv
  64. ATRACKS="${ATRACKS-0}" # n[:lng][,m[:lng]]..., can also change with --audiotracks
  65. # add your own filters if you want
  66. POSTVIDFILTERS="${POSTVIDFILTERS-}" #must include , at end
  67. ENDVIDFILTERS="${ENDVIDFILTERS-}"   #must include , at end
  68. # Disable some output checks. Can have multiple. e.g. OUTPUTCHECKS="NOSIZERATIO,NOSCAN"
  69. OUTPUTCHECKS="${OUTPUTCHEKS-}" # NOSIZE,NOVIDINFO,NOSIZERATIO,NOFRAMECOUNT,NOSCAN can also change with --outputchecks argument.
  70. # Boinc passwd, if you run boinc and want to disable it during transcode
  71. readonly BOINCPASSWD="${BOINCPASSWD-}"
  72. # Use mediainfo if available to identify video properties.
  73. USEMEDIAINFO="${USEMEDIAINFO-TRUE}" # TRUE or FALSE
  74. # default quality profile
  75. QUALITY="${QUALITY-med}"
  76.  
  77. #
  78. PATH=~mythtv/bin:${HOME}/bin:$PATH:/usr/local/bin
  79. # these variables will be recalled, if temporarily overriden, on every file change
  80. RECALL="ASPECTINLINE DENOISE POSTVIDFILTERS DEBLOCK DEINTERLACE INVTELECINE CROP CROPSIZE DELETEREC CHAPTERDURATION \
  81. CHAPTERFILE COPYDIR CONTYPE QUICKTIME_MP4 MKVAUD AVIVID PASS SCALE43 SCALE169 LAVC_CQ LAVC_OPTS XVID_CQ XVID_OPTS \
  82. MP3_ABITRATE X264_CQ X264EXT_OPTS X264_OPTS AAC_AQUAL OGG_AQUAL ATRACKS TITLE SUBTITLE"
  83. # these variables will be clean on every file change
  84. CLEAN="META_SEASON META_EPISODE META_ARTIST META_DIRECTOR META_ALBUM META_COMMENT META_LOCATION META_DATE"
  85.    
  86.  
  87. ##### Mapping #############################################################################################
  88. # Maps tvguide categories to mythvideo ones. This will need to be managed individually.
  89. # Either use the defaults below or create a mythnuv2mkv-category-mappings file in the same
  90. # directory as this and enter data same format as below.
  91. readonly CMAPFILE="$(dirname ${0})/mythnuv2mkv-category-mappings"
  92. if [ -f "$CMAPFILE" ]
  93. then
  94.     . "$CMAPFILE"
  95. else
  96.     # NOTE: Remove any spaces from XMLTV category. e.g. "Mystery and Suspense" is MysteryandSuspense
  97.     # XMLTV Category         ; Myth videocategory
  98.     readonly Animated=1      ; mythcat[1]="Animation"
  99.     readonly Biography=2         ; mythcat[2]="Documentary"
  100.     readonly Historical=3        ; mythcat[3]="Documentary"
  101.     readonly CrimeDrama=4        ; mythcat[4]="CrimeDrama"
  102.     readonly MysteryandSuspense=5    ; mythcat[5]="Mystery"
  103.     readonly Technology=6        ; mythcat[6]="Documentary"
  104.     readonly ScienceFiction=7    ; mythcat[7]="Sci-Fi"
  105.     readonly Science_Fiction=8   ; mythcat[8]="Sci-Fi"
  106.     readonly art=9           ; mythcat[9]="Musical"
  107.     readonly History=10      ; mythcat[10]="Documentary"
  108.     readonly SciFi=11        ; mythcat[11]="Sci-Fi"
  109.     readonly ScienceNature=12    ; mythcat[12]="Science"
  110. fi
  111.  
  112. ##########################################################################################################
  113. USAGE='mythnuv2mkv.sh [--jobid=%JOBID%] [--contype=avi|mkv|mp4] [--quality=low|med|high|480|576|720|1080] [--pass=one|two] [--denoise=ON|OFF] [--deblock=ON|OFF] [--deleterec=ON|OFF] [--aspect=4:3|16:9] [--crop=ON|OFF] [--deinterlace=ON|OFF|SOURCENAME] [--invtelecine=ON|OFF] [--outputchecks=notype] [[--chapterduration=mins] | [--chapterfile=file]] [--maxrunhours=int] [--findtitle=string] [--copydir=directory] "--chanid=chanid --starttime=starttime" | file ...
  114. Must have either --chanid=chanid and --starttime=starttime or a plain filename. These can be mixed. e.g. -
  115. mythnuv2mkv.sh --chanid=1232 --starttime=20071231235900 video1 video2 --chanid=1235 --starttime=20071231205900
  116. --jobid=%JOBID%
  117.        Add this when run as a User Job. Enables update status in the System Status Job Queue screen and the Job Queue Comments field in MythWeb. Also enables stop/pause/resume of job.
  118. --contype=avi|mkv|mp4 (default name of script. e.g. mythnuv2mkv.sh will default to mkv. mythnuv2avi.sh will default to avi)
  119.     (Note Videos staying in MythRecord will always default to avi)
  120.     avi - Video mpeg4 Audio mp3 (--contype=avi,xvid will use xvid instead of lavc)
  121.     mkv - Video h.264 Audio aac (--contype=mkv,ogg will use ogg Vorbis Audio)
  122.     mp4 - Video h.264 Audio aac
  123. --quality=low|med|high|720|1080 (default med) Mostly affects resolution.
  124.     low  - 448x336(4:3) or 592x336(16:9)
  125.     med  - 512x384(4:3) or 624x352(16:9)
  126.     high - 528x400(4:3) or 656x368(16:9)
  127.     480  - 640x480(4:3) or 848x480(16:9)
  128.     576  - 768x576(4:3) or 1024x576(16:9)
  129.     720  - 1280x720(16:9) (You probably need VDAPU to play this)
  130.     1080 - 1920x1088(16:9) (You probably need VDAPU to play this)
  131. --pass=one|two (default two)
  132.     --quality --pass and --contype can be passed as any argument and will only take effect on files after them.
  133.     e.g. mythnuv2mkv.sh videofile1 --chanid=2033 --starttime=20070704135700 --pass=one video3 --quality=low video4
  134.     videofile1 and chanid=2033/starttime=20070704135700 will be two pass med quality (defaults)
  135.     video3, one pass med quality
  136.     video4, one pass low quality
  137. --audiotracks=n[:lng][,m[:lng]]... (default empty)
  138.     audio tracks and, optionally, their language code, in the order they are supposed to be added to the output file (language codes and multiple tracks only supported in mp4 and mkv),
  139.     empty means one track, whichever mythtranscode chooses by default
  140. --maxrunhours=int (default process all files)
  141.     Stop processing files after int hours. (Will complete the current file it is processing.)
  142. --findtitle="string"
  143.     Prints tile, chanid, starttime of programs matching string.
  144. --copydir=directory
  145.     mkv/mp4/avi file will be created in directory. Source nuv will be retained. i.e you are copying the source rather than replacing it.
  146.     If the source was a CHANID/STARTIME it will be renamed to TITLE,S##E##,SUBTITLE. S##E## is the Season and Episode number. All punctuation characters are removed.
  147.     For MythTV 0.21 - If directory is under MythVideoDir, imdb will be searched, a MythVideo db entry created and a coverfile file created if one was not available at imdb.
  148.     For MythTV 0.22 - If directory is under MythVideoDir, no action taken. Use MythVideo tools, e.g. Metadata menu, jamu.
  149. --denoise=[ON|OFF] (default OFF)
  150.     Include hqdn3d denoise filter. 
  151. --deblock=[ON|OFF] (default OFF)
  152.     Include pp7 deblock filter.
  153. --deleterec=[ON|OFF] (default OFF)
  154.     Delete the recording after successful transcode. (Actually just sets high priority autoexpire and moves to Deleted group.)
  155. --crop=[ON|OFF] (default ON)
  156.     Crop 8 pixels of each side.
  157. --aspect=[4:3|16:9] Force aspect.
  158. --deinterlace==[ON|OFF|SOURCENAME] (default ON)
  159.     Include pp=fd deinterlace filter.
  160.     SOURCENAME is ON for that source. Can have multiple. e.g. DEINTERLACE="Cabel,FTA1"
  161. --invtelecine=[ON|OFF] (default OFF)
  162.     Include pullup inverse telecine filter.
  163.     Note/ This filter will not be added if a deinterlace filter has been added.
  164. --outputchecks=[NOSIZE,NOVIDINFO,NOSIZERATIO,NOFRAMECOUNT,NOSCAN] (default All checks ON)
  165.     Disable a output check. Set to one or many of the checks. e.g. OUTPUTCHECKS="NOSIZERATIO,NOSCAN"
  166. ---chapterduration=mins
  167.     Add chapter marks to mkv/mp4 files every mins minutes.
  168. ---chapterfile=file
  169.     Add chapter marks to mkv/mp4 as per chapter file. See mkvmerge or MP4Box manual for chapter file format.
  170.     (spaces not supported in chapter file name)
  171.  
  172. Logs to /var/tmp/mythnuv2mkvPID.log and to database if "log MythTV events to database" is enabled in mythtv.
  173. Cutlists are always honored.
  174. Sending the mythnuv2mkv.sh process a USR1 signal will cause it to stop after completing the current file.
  175. e.g. kill -s USR1 PID
  176. If run as a Myth Job, you can find the PID in the System Status Job Queue or Log Entries screens as [PID]
  177.  
  178. Typical usage.
  179.  
  180. Myth User Job
  181. PATH/mythnuv2mkv.sh --jobid=%JOBID% --copydir /mythvideodirectory --chanid=%CHANID% --starttime=%STARTTIME%
  182. This will convert nuv to mkv and copy it to /mythvideodirectory.
  183. This is what I do. Record things in Myth Recording and anything I want to keep, use this to convert to mkv and store in Myth Video.
  184. NOTE. System Status Job Queue screen and the Job Queue Comments field in MythWeb always report job Completed Successfully even if it actually failed.
  185.  
  186. Myth Video
  187. Record program
  188. mythrename.pl --link --format %T-%S --underscores --verbose (mythrename.pl is in the mythtv contrib directory
  189. cp from your mythstore/show_names/PROGRAM to your MythVideo directory
  190. use video manager to add imdb details
  191. nuv files work fine in MythVideo, but if you need to convert them to mkv/mp4/avi, or need to reduce their size
  192. run mythnuv2mkv.sh MythVideo_file.nuv
  193.  
  194. Myth Recording
  195. Record program
  196. run mythnuv2mkv.sh --findtitle="title name"
  197. get chanid and starttime
  198. run mythnuv2mkv.sh --chanid=chanid --starttime=starttime
  199. NOTE You cannot edit a avi/mp4/mkv file in Myth Recording. So do all your editing in the nuv file before you convert to avi.
  200. NOTE You cannot play a mkv/mp4 file in Myth Recording.
  201. I would in general recommend leaving everything in Myth Recording as nuv.
  202.  
  203. You can override most options for a specific recording by adding tags to the subtitle in MythTV, for example a subtitle of the form:
  204.  "Some subtitle r|David Lynch q|1080 f|mp4 crop|NO"
  205.  Will result in:
  206.    - subtitle:"Some subtitle"
  207.    - director: "David Lynch"
  208.    - quality: 1080
  209.    - container: mp4
  210.    - crop: NO
  211.  Available tags:
  212.    t: title
  213.    s: subtitle / episode title
  214.    n: season number
  215.    e: episode number
  216.    a: artist
  217.    r: director
  218.    b: album
  219.    c: comment
  220.    l: location
  221.    y|d: year / date (YYYY / YYYY-MM-DD / DD-MM-YYYY / DD.MM.YYYY etc.)
  222.    q: quality
  223.    f: container format
  224.    aud: audio track definitions
  225.    asp: aspect ratio
  226.    den: denoise filter
  227.    deb: deblock filter
  228.    dei: deinterlace
  229.    inv: inverse telecine
  230.    crop: cropping
  231.    del: delete recording
  232.    chap: chapter length
  233.    chapf: chapter file
  234.    dir: copy directory
  235.    pass: encoding pass count
  236.  
  237. Version: $Revision: 1.91 (beta) $ $Date: 2011/03/23 01:13:12 $
  238. '
  239. REQUIREDAPPS='
  240. Required Applications
  241. For all contypes
  242. mythtranscode.
  243. perl
  244. mplayer http://www.mplayerhq.hu/design7/news.html
  245. mencoder http://www.mplayerhq.hu/design7/news.html
  246. wget http://www.gnu.org/software/wget/
  247. ImageMagick http://www.imagemagick.org/script/index.php
  248. For avi
  249. mp3lame http://www.mp3dev.org
  250. xvid http://www.xvid.org/
  251. For mkv and mp4 contypes
  252. x264 http://www.videolan.org/developers/x264.html
  253. faac http://sourceforge.net/projects/faac/
  254. faad2 http://sourceforge.net/projects/faac/
  255. For mkv contype
  256. mkvtoolnix http://www.bunkus.org/videotools/mkvtoolnix/
  257. For mkv,ogg contype
  258. vorbis-tools http://www.vorbis.com/
  259. For mp4 contype
  260. MP4Box http://gpac.sourceforge.net/index.php
  261. '
  262. HELP=${USAGE}${REQUIREDAPPS}
  263.  
  264. ##### Pre Functions ###########################################
  265. preversioncheck() {
  266. local PRODUCT="$1"
  267. local LIBX264
  268.     case $PRODUCT in
  269.         libx264)
  270.             LIBX264=$(ldd $(which mencoder) | awk '/libx264/ {print $3}')
  271.             if strings "$LIBX264" | grep MB-tree >/dev/null 2>&1
  272.             then
  273.                 # Actually won't be used as currently (23/11/09) b_pyramid is disabled when MB-tree used
  274.                 # At some point b_pyramid may be added, so leaving this in
  275.                 NOBPYRAMID="b_pyramid=none:" # Global
  276.                 BPYRAMID="b_pyramid=normal:" # Global
  277.             else
  278.                 NOBPYRAMID="nob_pyramid:" # Global
  279.                 BPYRAMID="b_pyramid:" # Global
  280.             fi
  281.             if strings "$LIBX264" | grep force-cfr >/dev/null 2>&1
  282.             then
  283.                 FORCECFR="force_cfr:" # Global
  284.             else
  285.                 FORCECFR="" # Global
  286.             fi
  287.                ;;
  288.     esac
  289. }
  290.  
  291. ###########################################################
  292. readonly AVIREQPROGS="mencoder mythtranscode mplayer perl wget convert"
  293. readonly AVIREQLIBS="libmp3lame.so libxvidcore.so"
  294. readonly MP4REQPROGS="mencoder mythtranscode mplayer perl wget convert faac MP4Box"
  295. readonly MP4REQLIBS="libx264.so"
  296. readonly MKVREQPROGS="mencoder mythtranscode mplayer perl wget convert faac oggenc mkvmerge"
  297. readonly MKVREQLIBS="libx264.so"
  298. ###########################################################
  299. readonly DENOISEFILTER="hqdn3d"
  300. readonly DEBLOCKFILTER="pp7"
  301. readonly DEINTERLACEFILTER="pp=fd"
  302. readonly INVTELECINEFILTER="pullup"
  303. readonly FAACCHANCONFIG="-I 5,6"
  304. readonly TE_SCALE43="NA"        # NA
  305. readonly ST_SCALE43="NA"        # NA
  306. readonly FE_SCALE43="640:480"       # 1.32
  307. readonly FS_SCALE43="768:576"       # 1.32
  308. readonly HIGH_SCALE43=528:400       # 1.32
  309. readonly MED_SCALE43=512:384        # 1.333
  310. readonly LOW_SCALE43=448:336        # 1.333
  311. readonly TE_SCALE169="1920:1088"    # 1.778
  312. readonly ST_SCALE169="1280:720"     # 1.778
  313. readonly FE_SCALE169="848:480"      # 1.766
  314. readonly FS_SCALE169="1024:576"     # 1.778
  315. readonly HIGH_SCALE169=656:368      # 1.783
  316. readonly MED_SCALE169=624:352       # 1.773
  317. readonly LOW_SCALE169=592:336       # 1.762
  318. # Default
  319. SCALE43=$MED_SCALE43
  320. SCALE169=$MED_SCALE169
  321. ###########################################################
  322. ## CQ ## Quote from mencoder documentation
  323. #The CQ depends on the bitrate, the video codec efficiency and the movie resolution. In order to raise the CQ, typically you would
  324. #downscale the movie given that the bitrate is computed in function of the target size and the length of the movie, which are constant.
  325. #With MPEG-4 ASP codecs such as Xvid and libavcodec, a CQ below 0.18 usually results in a pretty blocky picture, because there are
  326. #not enough bits to code the information of each macroblock. (MPEG4, like many other codecs, groups pixels by blocks of several pixels
  327. #to compress the image; if there are not enough bits, the edges of those blocks are visible.) It is therefore wise to take a CQ ranging
  328. # from 0.20 to 0.22 for a 1 CD rip, and 0.26-0.28 for 2 CDs rip with standard encoding options. More advanced encoding options such as
  329. #those listed here for libavcodec and Xvid should make it possible to get the same quality with CQ ranging from 0.18 to 0.20 for a 1 CD
  330. #rip, and 0.24 to 0.26 for a 2 CD rip. With MPEG-4 AVC codecs such as x264, you can use a CQ ranging from 0.14 to 0.16 with standard
  331. #encoding options, and should be able to go as low as 0.10 to 0.12 with x264's advanced encoding settings.
  332. ########################
  333. # These map to --quality=low|med|high option.
  334. #### AVI lavc mpeg4 ####
  335. readonly HIGH_LAVC_CQ=0.22
  336. readonly MED_LAVC_CQ=0.21
  337. readonly LOW_LAVC_CQ=0.20
  338. readonly HIGH_LAVC_OPTS="vcodec=mpeg4:threads=${THREADS}:mbd=2:trell:v4mv:last_pred=2:dia=-1:vmax_b_frames=2:vb_strategy=1:cmp=3:subcmp=3:precmp=0:vqcomp=0.6"
  339. # high, med & low will use same settings just CQ and resolution different
  340. # This make encoding slow. Swap following if you want lower quality to also mean faster encoding speed.
  341. #readonly MED_LAVC_OPTS="vcodec=mpeg4:mbd=2:trell:v4mv"
  342. #readonly LOW_LAVC_OPTS="vcodec=mpeg4:mbd=2"
  343. readonly MED_LAVC_OPTS="$HIGH_LAVC_OPTS"
  344. readonly LOW_LAVC_OPTS="$HIGH_LAVC_OPTS"
  345. #### AVI xvid mpeg4 ####
  346. readonly HIGH_XVID_CQ=0.22
  347. readonly MED_XVID_CQ=0.21
  348. readonly LOW_XVID_CQ=0.20
  349. readonly HIGH_XVID_OPTS="threads=${THREADS}:quant_type=mpeg:me_quality=6:chroma_me:chroma_opt:trellis:hq_ac:vhq=4:bvhq=1"
  350. readonly MED_XVID_OPTS="$HIGH_XVID_OPTS"
  351. readonly LOW_XVID_OPTS="$HIGH_XVID_OPTS"
  352. #### AVI lavc/xvid mp3 ####
  353. readonly HIGH_MP3_ABITRATE=256
  354. readonly MED_MP3_ABITRATE=192
  355. readonly LOW_MP3_ABITRATE=128
  356. #### MP4/MKV h.263/aac,ogg ####
  357. readonly HIGH_X264_CQ=0.15
  358. readonly MED_X264_CQ=0.14
  359. readonly LOW_X264_CQ=0.13
  360. preversioncheck "libx264" # Sets BPYRAMID & NOBPYRAMID & FORCECFR
  361. # H.264 Extended profile (quicktime) level set in QLEVEL
  362. readonly HIGH_X264EXT_OPTS="nocabac:bframes=2:${FORCECFR}${NOBPYRAMID}threads=auto:direct_pred=auto:subq=6:frameref=5"
  363. # high, med & low will use same settings just CQ and resolution different
  364. # This make encoding slow. Swap following if you want lower quality to also mean faster encoding speed.
  365. #readonly MED_X264EXT_OPTS="nocabac:bframes=2:${FORCECFR}${NOBPYRAMID}threads=auto:subq=5:frameref=4"
  366. #readonly LOW_X264EXT_OPTS="nocabac:bframes=2:${FORCECFR}${NOBPYRAMID}threads=auto:subq=4:frameref=3"
  367. readonly MED_X264EXT_OPTS="$HIGH_X264EXT_OPTS"
  368. readonly LOW_X264EXT_OPTS="$HIGH_X264EXT_OPTS"
  369. # H.264 High profile level set in QLEVEL
  370. readonly HIGH_X264HIGH_OPTS="bframes=3:${FORCECFR}${BPYRAMID}weight_b:threads=auto:direct_pred=auto:subq=6:frameref=5:partitions=all:8x8dct:mixed_refs:me=umh:trellis=1"
  371. # high, med & low will use same settings just CQ and resolution different
  372. # This make encoding slow. Swap following if you want lower quality to also mean faster encoding speed.
  373. #readonly MED_X264HIGH_OPTS="bframes=3:${FORCECFR}${BPYRAMID}weight_b:threads=auto:subq=5:frameref=4:8x8dct"
  374. #readonly LOW_X264HIGH_OPTS="bframes=3:${FORCECFR}${BPYRAMID}weight_b:threads=auto:subq=4:frameref=3"
  375. readonly MED_X264HIGH_OPTS="$HIGH_X264HIGH_OPTS"
  376. readonly LOW_X264HIGH_OPTS="$HIGH_X264HIGH_OPTS"
  377. # AAC
  378. readonly HIGH_AAC_AQUAL=100
  379. readonly MED_AAC_AQUAL=90
  380. readonly LOW_AAC_AQUAL=80
  381. # OGG
  382. readonly HIGH_OGG_AQUAL=6
  383. readonly MED_OGG_AQUAL=5
  384. readonly LOW_OGG_AQUAL=4
  385. # Defaults
  386. LAVC_OPTS=$MED_LAVC_OPTS
  387. LAVC_CQ=$MED_LAVC_CQ
  388. XVID_OPTS=$MED_XVID_OPTS
  389. XVID_CQ=$MED_XVID_CQ
  390. MP3_ABITRATE=$MED_MP3_ABITRATE
  391. AAC_AQUAL=$MED_AAC_AQUAL
  392. OGG_AQUAL=$MED_OGG_AQUAL
  393. X264EXT_OPTS="level_idc=31:$MED_X264EXT_OPTS"
  394. X264_OPTS="level_idc=31:$MED_X264HIGH_OPTS"
  395. X264_CQ=$MED_X264_CQ
  396. if echo "$(basename $0)" | grep -i 'mkv' >/dev/null 2>&1
  397. then
  398.     CONTYPE="mkv"
  399.     QUICKTIME_MP4="NO"
  400. elif echo "$(basename $0)" | grep -i 'mp4' >/dev/null 2>&1
  401. then
  402.     CONTYPE="mp4"
  403.     QUICKTIME_MP4="NO"
  404. elif echo "$(basename $0)" | grep -i 'mov' >/dev/null 2>&1
  405. then
  406.     #TODO. Not working yet don't use mov
  407.     CONTYPE="mp4"
  408.     QUICKTIME_MP4="YES"
  409. elif echo "$(basename $0)" | grep -i 'avi' >/dev/null 2>&1
  410. then
  411.     CONTYPE="avi"
  412.     QUICKTIME_MP4="NO"
  413. fi
  414. ###########################################################
  415. # ON or OFF
  416. # debug mode
  417. DEBUG="OFF"
  418. DEBUGSQL="OFF"
  419. DEBUGSG="OFF"
  420. # Print INFO messages
  421. INFO="ON"
  422. # Save(via a rename) or delete nuv file. Only for transcode back into MythRecording.
  423. SAVENUV="OFF"
  424.  
  425. [ "$DEBUGSQL" = "ON" ] && DEBUG="ON"
  426.  
  427. ##### Functions ###########################################
  428. scriptlog() {
  429. local LEVEL="$1"
  430. shift
  431. local PRIORITY
  432. local HIGHLIGHTON
  433. local HIGHLIGHTOFF
  434.     if [ "$LEVEL" = "BREAK" ]
  435.     then
  436.         echo "--------------------------------------------------------------------------------" | tee -a $LOGFILE
  437.         return 0
  438.     elif [ "$LEVEL" = "ERROR" ]
  439.     then
  440.         PRIORITY=4
  441.         HIGHLIGHTON="${REDFG}"
  442.         HIGHLIGHTOFF="${COLOURORIG}"
  443.         FINALEXIT=1 # Global
  444.     elif [ "$LEVEL" = "WARN" ]
  445.     then
  446.         PRIORITY=4
  447.         HIGHLIGHTON="${REDFG}"
  448.         HIGHLIGHTOFF="${COLOURORIG}"
  449.     elif [ "$LEVEL" = "SUCCESS" ]
  450.     then
  451.         PRIORITY=5
  452.         HIGHLIGHTON="${GREENFG}"
  453.         HIGHLIGHTOFF="${COLOURORIG}"
  454.     elif [ "$LEVEL" = "START" -o "$LEVEL" = "STOP" ]
  455.     then
  456.         PRIORITY=5
  457.         HIGHLIGHTON="${BOLDON}"
  458.         HIGHLIGHTOFF="${ALLOFF}"
  459.     elif [ "$LEVEL" = "DEBUG" ]
  460.     then
  461.         [ "$DEBUG" = "ON" ] || return
  462.         PRIORITY=7
  463.         HIGHLIGHTON=""
  464.         HIGHLIGHTOFF=""
  465.     elif [ "$LEVEL" = "NOHEADER" ]
  466.     then
  467.         # Also no db logging
  468.         echo "$*" | tee -a $LOGFILE
  469.         return
  470.     else
  471.         [ "$INFO" = "ON" ] || return
  472.         LEVEL="INFO"
  473.         PRIORITY=6
  474.         HIGHLIGHTON=""
  475.         HIGHLIGHTOFF=""
  476.     fi
  477.     echo "${HIGHLIGHTON}$(date +%d/%m,%H:%M) [${$}] $LEVEL $*${HIGHLIGHTOFF}" | tee -a $LOGFILE
  478.  
  479.     [ "$DBLOGGING" -eq 1 ] && insertmythlogentry "$PRIORITY" "$LEVEL" "${$}" "$*"
  480. }
  481.  
  482. versioncheck() {
  483. local PRODUCT="$1"
  484. local VER
  485. local MAJ
  486. local MIN
  487. local PAT
  488.     case $PRODUCT in
  489.         mkvmerge)
  490.             VER=$(mkvmerge -V | awk '/mkvmerge/ {print $2}')
  491.             OLDIFS="$IFS"; IFS="."; set - $VER; IFS="$OLDIFS"
  492.             MAJ=$(echo "$1" | tr -d '[:alpha:]'); MIN="$2"; PAT="$3"
  493.             if [ "$VER" = "v2.5.1" ]
  494.             then
  495.                 scriptlog INFO "mkvmerge v2.5.1. There is a known bug with this version. Workaround applied."
  496.                 MKVMERGE251BUG="YES" # Global
  497.             elif [ "$MAJ" -lt 2 -o \( "$MAJ" -eq 2 -a "$MIN" -lt 2 \) ]
  498.             then
  499.                 scriptlog INFO "mkvmerge $VER. This will not work with 29.97 fps video (NTSC). You need at least v2.2.0"
  500.             fi
  501.             scriptlog DEBUG "mkvmerge $VER"
  502.             return 0
  503.         ;;
  504.         convert)
  505.             # There are several programs called convert. Check it is ImageMagick.
  506.             convert -version 2>&1 | grep -i 'ImageMagick' >/dev/null 2>&1 && return 0 || return 1
  507.         ;;
  508.     esac
  509. }
  510.  
  511. chkreqs() {
  512. local REQPROGS="$1"
  513. local REQLIBS="$2"
  514. local TMP
  515. local MENCODER
  516.     for TMP in $REQPROGS
  517.     do
  518.         if ! which "$TMP" >/dev/null 2>&1
  519.         then
  520.             scriptlog ERROR "Can't find program $TMP."
  521.             scriptlog ERROR "$REQUIREDAPPS"
  522.             return 1
  523.         fi
  524.     done
  525.     MENCODER=$(which mencoder)
  526.     for TMP in $REQLIBS
  527.     do
  528.         if ! ldd $MENCODER | grep -i  "${TMP}.*=>.*${TMP}" >/dev/null 2>&1
  529.         then
  530.             scriptlog ERROR "mencoder may not support $TMP."
  531.             scriptlog ERROR "$REQUIREDAPPS"
  532.             return 1
  533.         fi
  534.     done
  535.     return 0
  536. }
  537.  
  538. calcbitrate() {
  539. local ASPECT=$1
  540. local SCALE=$2
  541. local CQ=$3
  542. local W
  543. local H
  544. local BITRATE
  545.     W=$(echo $SCALE | cut -d ':' -f1)
  546.     H=$(echo $SCALE | cut -d ':' -f2)
  547.     BITRATE=$(echo "((($H^2 * $ASPECT * 25 * $CQ) / 16 ) * 16) / 1000" | bc)
  548.     echo $BITRATE
  549. }
  550.  
  551. getsetting() {
  552. local VALUE="$1"
  553. local HOST=$(hostname)
  554. local DATA
  555.     DATA=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  556.     select data from settings where value = "$VALUE" and hostname like "${HOST}%";
  557.     EOF
  558.     )
  559.     if [ -z "$DATA" ]
  560.     then
  561.         DATA=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  562.         select data from settings where value = "$VALUE" and (hostname is NULL or hostname = "");
  563.     EOF
  564.     )
  565.     fi
  566.     echo "$DATA"
  567. }
  568.  
  569. # Not Used.
  570. getstoragegroupdirs() {
  571.     mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  572.     select distinct dirname from storagegroup;
  573.     EOF
  574. }
  575.  
  576. hascutlist() {
  577. local CHANID="$1"
  578. local STARTTIME="$2"
  579. local DATA
  580.     [ -n "$CHANID" ] || return 1
  581.     DATA=$(mysql --batch --skip-column-name --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  582.     select cutlist from recorded where chanid = $CHANID and starttime = "$STARTTIME";
  583.     EOF
  584.     )
  585.     [ "$DATA" -eq 1 ] && return 0 || return 1
  586. }
  587.  
  588. getrecordfile() {
  589. local CHANID="$1"
  590. local STARTTIME="$2"
  591. local DEBUGSG="$3"
  592. local DATA
  593. local DATALINE
  594. local RECFILE
  595. local SGHOST
  596.     [ -n "$CHANID" ] || return 1
  597.     # Storage groups
  598.     if [ "$DEBUGSG" = "ON" ]
  599.     then
  600.         scriptlog INFO "CHANID $CHANID STARTTIME $STARTTIME"
  601.         DATA=$(mysql --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  602.         select * from storagegroup;
  603.         select chanid,starttime,title,subtitle,basename,storagegroup from recorded where chanid = $CHANID and starttime = "$STARTTIME";
  604.         EOF
  605.         )
  606.         scriptlog INFO "Tables"
  607.         scriptlog NOHEADER "$DATA"
  608.     fi
  609.     DATA=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  610.     select a.hostname,':::',concat(a.dirname, "/", b.basename) from storagegroup a, recorded b where b.chanid = $CHANID and b.starttime = "$STARTTIME" and b.storagegroup = a.groupname;
  611.     EOF
  612.     )
  613.     [ "$DEBUGSG" = "ON" ] && scriptlog INFO "Try 1 Data $DATA"
  614.     while read DATALINE
  615.     do
  616.         SGHOST=$(echo "$DATALINE" | awk -F':::' '{print $1}' | sed -e 's/[ \t]*\(.*\)[ \t]*/\1/')
  617.         RECFILE=$(echo "$DATALINE" | awk -F':::' '{print $2}' | sed -e 's/[ \t]*\(.*\)[ \t]*/\1/')
  618.         [ "$DEBUGSG" = "ON" ] && scriptlog INFO "Try 1 Check SGHost $SGHOST RecFile $RECFILE"
  619.         [ -f "${RECFILE}" ] && break
  620.     done < <(echo "$DATA")
  621.     if [ ! -f "$RECFILE" ]
  622.     then
  623.         # Pre Storage groups
  624.         local RFP=$(getsetting RecordFilePrefix)
  625.         DATA=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  626.         select concat("$RFP", "/", basename) from recorded where chanid = $CHANID and starttime = "$STARTTIME" limit 1;
  627.         EOF
  628.         )
  629.         [ "$DEBUGSG" = "ON" ] && scriptlog INFO "Try 2 $RFP,$DATA"
  630.         RECFILE="$DATA"
  631.     fi
  632.     [ -f "$RECFILE" ] && echo "$RECFILE"
  633. }
  634.  
  635. getsourcename() {
  636. local CHANID="$1"
  637.     [ -n "$CHANID" ] || return 1
  638.     mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  639.     select b.displayname from channel a, cardinput b where a.chanid = $CHANID and a.sourceid = b.sourceid;
  640.     EOF
  641. }
  642.  
  643. gettitle() {
  644. local CHANID="$1"
  645. local STARTTIME="$2"
  646.     [ -n "$CHANID" ] || return 1
  647.     mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  648.     select title from recorded where chanid = $CHANID and starttime = "$STARTTIME";
  649.     EOF
  650. }
  651.  
  652. getsubtitle() {
  653. local CHANID="$1"
  654. local STARTTIME="$2"
  655.     [ -n "$CHANID" ] || return 1
  656.     mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  657.     select subtitle from recorded where chanid = $CHANID and starttime = "$STARTTIME";
  658.     EOF
  659. }
  660.  
  661. findchanidstarttime() {
  662. local SEARCHTITLE="$1"
  663.     mysql --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  664.     select title, subtitle, chanid, date_format(starttime, '%Y%m%d%H%i%s'), storagegroup from recorded where title like "%${SEARCHTITLE}%";
  665.     EOF
  666. }
  667.  
  668. updatemetadata() {
  669. local NEW="$1"
  670. local CHANID="$2"
  671. local STARTTIME="$3"
  672. local NFSIZE
  673.     NFSIZE=$(stat -c %s "$NEW")
  674.     NEW=$(basename "$NEW")
  675.     mysql --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  676.     update recorded set
  677.     basename = "$NEW",
  678.     filesize = $NFSIZE,
  679.     bookmark = 0,
  680.     editing = 0,
  681.     cutlist = 0,
  682.     commflagged = 0
  683.     where chanid = $CHANID and starttime = "$STARTTIME";
  684.     delete from recordedmarkup where chanid = $CHANID and starttime = "$STARTTIME";
  685.     delete from recordedseek where chanid = $CHANID and starttime = "$STARTTIME";
  686.     EOF
  687. }
  688.  
  689. createvideocover() {
  690. local CFDIR="$1"
  691. local FILENAME="$2"
  692. local ASPECT="$3"
  693. local THDIR="${FIFODIR}/THDIR"
  694. local THUMB_NAME=$(basename "$FILENAME" | sed -e 's/\.[am][vkp][iv4]$/\.png/')
  695. local THUMB_PATH="${CFDIR}/${THUMB_NAME}"
  696. local CURWD
  697. local TH
  698.     {
  699.     CURWD=$(pwd)
  700.     mkdir $THDIR && cd $THDIR || return 1
  701.     nice -19 mplayer -really-quiet -nojoystick -nolirc -nomouseinput -ss 00:02:00 -aspect $ASPECT -ao null -frames 50 -vo png:z=5 "$FILENAME"
  702.     TH=$(ls -1rt | tail -1)
  703.     [ -f "$TH" ] || return
  704.     if [ $ASPECT = "16:9" ]
  705.     then
  706.         convert "$TH" -resize 720x404! THWS.png
  707.     else
  708.         cp "$TH" THWS.png
  709.     fi
  710.     mv THWS.png "$THUMB_PATH"
  711.     cd $CURWD
  712.     rm -rf "$THDIR"
  713.     } >/dev/null 2>&1
  714.     echo "$THUMB_PATH"
  715. }
  716.  
  717. getsearchtitle() {
  718. local CHANID="$1"
  719. local STARTTIME="$2"
  720. local TI
  721. local ST
  722. local SEARCHTITLE
  723.     [ -n "$CHANID" ] || return 1
  724.     if [ -n "$TITLE" -a -n "$SUBTITLE" ]
  725.     then
  726.         SEARCHTITLE="${TITLE}:${SUBTITLE}"
  727.     elif [ -n "$TITLE" ]
  728.     then
  729.         SEARCHTITLE="${TITLE}"
  730.     fi
  731.     echo $SEARCHTITLE
  732. }
  733.  
  734. lookupinetref() {
  735. # : is used to separate Title and SubTitle in SEARCHTITLE
  736. local SEARCHTITLE="$1"
  737. local CHANID="$2"
  738. local STARTTIME="$3"
  739. local IMDBCMD
  740. local IMDBRES
  741. local IMDBSTR=""
  742. # INETREF will be 00000000 if not found
  743. local INETREF=00000000
  744. local SERIES
  745. local EPISODE
  746. local YEAR
  747. local TMP
  748.     {
  749.         IMDBCMD=$(getsetting MovieListCommandLine)
  750.     # This is dependent on imdb.pl and will not work with any MovieListCommandLine due to use of s=ep option.
  751.     set - $IMDBCMD
  752.     IMDBCMD="$1 $2"
  753.         IMDBRES=$($IMDBCMD "$SEARCHTITLE")
  754.         if [ -n "$IMDBRES" -a $(echo "$IMDBRES" | wc -l) -eq 1 ]
  755.         then
  756.         IMDBSTR="$IMDBRES"
  757.     elif [ -n "$CHANID" ]
  758.     then
  759.         YEAR=$(getyear $CHANID $STARTTIME)
  760.         if [ "$YEAR" -gt 1800 ]
  761.         then
  762.             for C in 0 1 -1
  763.             do
  764.                 TMP=$(echo "$IMDBRES" | grep $(( $YEAR + $C )))
  765.                 [ -n "$TMP" -a $(echo "$TMP" | wc -l) -eq 1 ] && IMDBSTR="$TMP" && break
  766.             done
  767.         fi
  768.         fi
  769.     if [ -n "$IMDBSTR" ]
  770.     then
  771.                 INETREF=$(echo "$IMDBSTR" | awk -F'[^0-9]' '{print $1}')
  772.                 echo $INETREF | grep '^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]*$' >/dev/null 2>&1 || INETREF=00000000
  773.     fi
  774.         if [ "$INETREF" -eq 00000000 ]
  775.         then
  776.         # Try looking for episode
  777.                 OLDIFS="$IFS"; IFS=":"; set - $SEARCHTITLE; IFS="$OLDIFS"
  778.         SERIES="$1" ; EPISODE="$2"
  779.         if [ -n "$SERIES" -a -n "$EPISODE" ]
  780.         then
  781.             # option s=ep is for episode lookup
  782.             IMDBSTR=$($IMDBCMD s=ep "$EPISODE")
  783.             if which agrep >/dev/null 2>&1
  784.             then
  785.                 IMDBSTR=$(echo "$IMDBSTR" | agrep -i -s -2 "$SERIES" | sort -n | head -1 | cut -d':' -f2-)
  786.             else
  787.                 IMDBSTR=$(echo "$IMDBSTR" | grep -i "$SERIES")
  788.             fi
  789.             if [ $(echo "$IMDBSTR" | wc -l) -eq 1 ]
  790.             then
  791.                 INETREF=$(echo "$IMDBSTR" | awk -F'[^0-9]' '{print $1}')
  792.                 echo $INETREF | grep '^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]*$' >/dev/null 2>&1 || INETREF=00000000
  793.             fi
  794.         fi
  795.         fi
  796.     scriptlog DEBUG "inetref $INETREF"
  797.     } >/dev/null 2>&1
  798.         echo $INETREF
  799. }
  800.  
  801. getseriesepisode() {
  802. local CHANID="$1"
  803. local STARTTIME="$2"
  804. local INETREF="$3"
  805. local DATA
  806. local SE
  807.     [ -n "$CHANID" ] || return 1
  808.  
  809.     if [ -n "$META_EPISODE" ]
  810.     then
  811.         SE=$(echo "$META_EPISODE" | awk "{ printf(\"${EPISODE_FORMAT}\", \$1) }")
  812.         [ -n "$META_SEASON" ] && SE=$(echo "|$SE|$META_SEASON|" | awk -F"|" "{ printf(\"${SEASON_FORMAT}\", \$2, \$3) }")
  813.     else   
  814.         # STARTTIME is not always the same in both tables for matching programs. ???
  815.         DATA=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  816.         select syndicatedepisodenumber from recorded a,recordedprogram b
  817.         where a.chanid = $CHANID and a.starttime = "$STARTTIME" and a.chanid = b.chanid
  818.         and a.title = b.title and a.subtitle = b.subtitle;
  819.         EOF
  820.         )
  821.         DATA=$(echo "$DATA" | awk -F '[SE]' "/S/ { printf(\"${SEASON_FORMAT}\", sprintf(\"${EPISODE_FORMAT}\", \$2), \$3) }")
  822.         if echo "$DATA" | egrep -q "${EPISODE_RE}"
  823.         then
  824.             SE="$DATA"
  825.         elif [ $INETREF -gt 0 ]
  826.         then
  827.             # Lets try passing imdb page
  828.             wget -o /dev/null -O "${FIFODIR}/${INETREF}.html" "http://www.imdb.com/title/tt${INETREF}/"
  829.             SE=$(awk "/Season.*Episode/ {
  830.             a=match(\$0,/Season ([0-9]+)/,s);b=match(\$0,/Episode ([0-9]+)/,e);
  831.             if(a>0 && b>0) {
  832.                 printf(\"${SEASON_FORMAT}\", sprintf(\"${EPISODE_FORMAT}\", e[1]), s[1]);exit}
  833.             }" "${FIFODIR}/${INETREF}.html")
  834.         fi
  835.     fi
  836.     echo "$SE" | egrep "$EPISODE_RE"
  837. }
  838.  
  839. createfiletitleSEsubtitle() {
  840. local CHANID="$1"
  841. local STARTTIME="$2"
  842. local SE="$3"
  843. local DATA
  844. local T
  845. local S
  846.     FILE="$TITLE"
  847.     [ -n "$META_ARTIST" ] && FILE="${META_ARTIST}${SEP}${FILE}"
  848.     [ -n "$SE" ] && FILE=$(echo "|$FILE|$SE|" | awk -F"|" "{ printf(\"${TITLE_FORMAT}\", \$2, \$3 ) }")
  849.     [ -z "$SE" -a -n "$SUBTITLE" ] && FILE="${FILE}${SEP}${SUBTITLE}"
  850.     [ -n "$SE" -a -n "$SUBTITLE" ] && FILE="${FILE}${SUBTITLE}"
  851.     [ -n "$META_DATE" ] && FILE=$(echo "|$FILE|$META_DATE" | awk -F"|" "{ printf(\"${DATE_FORMAT}\", \$2, \$3 ) }")
  852.     [ -n "$TR" ] && FILE=$(echo $FILE | tr -d '[:cntrl:]' | tr -d '[:punct:]' | tr '[:space:]' "$TR")
  853.     echo $FILE
  854. }
  855.  
  856. is21orless() {
  857.     local DATA=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  858.     select subtitle from videometadata limit 1;
  859.     EOF
  860.     )
  861.     echo "$DATA" | egrep 'ERROR.*Unknown column' >/dev/null 2>&1 && return 0 || return 1
  862. }
  863.  
  864. is24ormore() {
  865.     local DATA=$(mythtranscode --audiotrack 2>&1)
  866.     echo "$DATA" | grep -q 'Unknown option: --audiotrack' && return 1 || return 0
  867. }
  868.  
  869. createvideometadata() {
  870. local FILENAME="$1"
  871. local TITLE="$2"
  872. local ASPECT="$3"
  873. local CHANID="$4"
  874. local STARTTIME="$5"
  875. local INETREF="$6"
  876. # SE may be null
  877. local SE="$7"
  878. local DIRECTOR="Unknown"
  879. #local PLOT="None"
  880. local PLOT="$(getplot $CHANID $STARTTIME)"
  881. local MOVIERATING="NR"
  882. #local YEAR=1895
  883. local YEAR="$(getyear $CHANID $STARTTIME)"
  884. local USERRATING=0
  885. local RUNTIME=0
  886. local COVERFILE="No Cover"
  887. local GENRES=""
  888. local COUNTRIES=""
  889. local CATEGORY=""
  890. local CFDIR=$(getsetting "VideoArtworkDir")
  891. local TI
  892. local ST
  893. local IMDBCMD
  894. local IMDBSTR
  895. local GTYPE
  896. local TH
  897. local SE
  898. local S
  899. local E
  900. local WHERE
  901. local TMP
  902. local IDS
  903. local VIDID
  904. local COUNT
  905.     # Title name generation is a mess. Should do something better
  906.     if ! is21orless
  907.     then
  908.         scriptlog INFO "MythTV V0.22 or greater. Not creating MythVideo entry. Use MythVideo menu"
  909.         return 0
  910.     fi
  911.     if hasvideometadata "$FILENAME"
  912.     then
  913.         scriptlog INFO "$FILENAME already has a videometdata entry."
  914.         return 0
  915.     fi
  916.     # Since I strip special characters in TITLE, use chanid/starttime for metadata title.
  917.     if [ -n "$CHANID" ]
  918.     then
  919.         TI=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  920.         select title from recorded where chanid = $CHANID and starttime = "$STARTTIME";
  921.         EOF
  922.         )
  923.         ST=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  924.         select subtitle from recorded where chanid = $CHANID and starttime = "$STARTTIME";
  925.         EOF
  926.         )
  927.         if [ -n "$TI" -a -n "$SE" -a -n "$ST" ]
  928.         then
  929.             TITLE="\\\"${TI}\\\" ${SE} ${ST}"
  930.         elif [ -n "$TI" -a -n "$ST" ]
  931.         then
  932.             TITLE="\\\"${TI}\\\" ${ST}"
  933.         elif [ -n "$TI" ]
  934.         then
  935.             TITLE="${TI}"
  936.         fi
  937.     fi
  938.     if [ $INETREF -gt 0 ]
  939.     then
  940.         IMDBCMD=$(getsetting MovieDataCommandLine)
  941.         IMDBSTR=$($IMDBCMD $INETREF | sed -e 's/"/\\"/g')
  942.         TMP=$(echo "$IMDBSTR" | grep '^Title' | cut -d':' -f2- | sed -e 's/^ *//')
  943.         if [ -n "$TMP" ]
  944.         then
  945.             # Try and put series and episode number back in. Based on imdb placing quotes around series name. A bit dodgy
  946.             if [ -n "$SE" ]
  947.             then
  948.                 TMP=$(echo "$TMP" | awk -v s=${SE} '{
  949.                 r=match($0,/"(.*)" (.*)/,m)
  950.                 if(r>0) { print("\\\""m[1]"\\\" "s" "m[2]) }
  951.                 else { print($0) }
  952.                 }' | sed -e 's/\\\\"/\\"/g')
  953.             fi
  954.             TITLE="$TMP"
  955.         fi
  956.         TMP=$(echo "$IMDBSTR" | grep '^Year' | cut -d':' -f2- | sed -e 's/^ *//')
  957.         [ -n "$TMP" ] && YEAR="$TMP"
  958.         TMP=$(echo "$IMDBSTR" | grep '^Director' | cut -d':' -f2- | sed -e 's/^ *//')
  959.         [ -n "$TMP" ] && DIRECTOR="$TMP"
  960.         TMP=$(echo "$IMDBSTR" | grep '^Plot' | cut -d':' -f2- | sed -e 's/^ *//')
  961.         [ -n "$TMP" ] && PLOT="$TMP"
  962.         TMP=$(echo "$IMDBSTR" | grep '^UserRating' | grep -v '[<>\"]' | cut -d':' -f2- | sed -e 's/^ *//')
  963.         [ -n "$TMP" ] && USERRATING="$TMP"
  964.         TMP=$(echo "$IMDBSTR" | grep '^MovieRating' | cut -d':' -f2- | sed -e 's/^ *//')
  965.         [ -n "$TMP" ] && MOVIERATING="$TMP"
  966.         TMP=$(echo "$IMDBSTR" | grep '^Runtime' | cut -d':' -f2- | sed -e 's/^ *//')
  967.         [ -n "$TMP" ] && RUNTIME="$TMP"
  968.         IMDBCMD=$(getsetting MoviePosterCommandLine)
  969.         IMDBCOVER=$($IMDBCMD $INETREF)
  970.         if [ -n "$IMDBCOVER" ]
  971.         then
  972.             GTYPE=$(echo $IMDBCOVER | sed -e 's/.*\(\....\)/\1/')
  973.             wget -o /dev/null -O "${CFDIR}/${INETREF}${GTYPE}" $IMDBCOVER
  974.             [ -f "${CFDIR}/${INETREF}${GTYPE}" ] && COVERFILE="${CFDIR}/${INETREF}${GTYPE}"
  975.         fi
  976.         TMP=$(echo "$IMDBSTR" | grep '^Genres' | cut -d':' -f2- | sed -e 's/^ *//')
  977.         [ -n "$TMP" ] && GENRES="$TMP"
  978.         TMP=$(echo "$IMDBSTR" | grep '^Countries' | cut -d':' -f2- | sed -e 's/^ *//')
  979.         [ -n "$TMP" ] && COUNTRIES="$TMP"
  980.         TMP=$(echo "$IMDBSTR" | grep '^Cast' | cut -d':' -f2- | sed -e 's/^ *//')
  981.         [ -n "$TMP" ] && CASTMEMBERS="$TMP"
  982.     fi
  983.     if ! [ -f "$COVERFILE" ]
  984.     then
  985.         scriptlog INFO "Creating cover file."
  986.         TH=$(createvideocover "$CFDIR" "$FILENAME" $ASPECT)
  987.         [ -f ${TH} ] && COVERFILE="${TH}"
  988.     fi
  989.     scriptlog INFO "Creating videometadata entry. Inetref:$INETREF. Title:$TITLE"
  990.     if [ "$DEBUGSQL" = "ON" ]
  991.     then
  992.         cat <<-EOF
  993.         insert into videometadata set
  994.         title = "$TITLE",
  995.         director = "$DIRECTOR",
  996.         plot = "$PLOT",
  997.         rating = "$MOVIERATING",
  998.         inetref = "$INETREF",
  999.         year = $YEAR,
  1000.         userrating = $USERRATING,
  1001.         length = $RUNTIME,
  1002.         showlevel = 1,
  1003.         filename = "$FILENAME",
  1004.         coverfile = "$COVERFILE",
  1005.         childid = -1,
  1006.         browse = 1,
  1007.         playcommand = NULL,
  1008.         category = 0;
  1009.         EOF
  1010.     fi
  1011.     mysql --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1012.     insert into videometadata set
  1013.     title = "$TITLE",
  1014.     director = "$DIRECTOR",
  1015.     plot = "$PLOT",
  1016.     rating = "$MOVIERATING",
  1017.     inetref = "$INETREF",
  1018.     year = $YEAR,
  1019.     userrating = $USERRATING,
  1020.     length = $RUNTIME,
  1021.     showlevel = 1,
  1022.     filename = "$FILENAME",
  1023.     coverfile = "$COVERFILE",
  1024.     childid = -1,
  1025.     browse = 1,
  1026.     playcommand = NULL,
  1027.     category = 0;
  1028.     EOF
  1029.     CATEGORY=$(getcategory "$CHANID" "$STARTTIME")
  1030.     if [ -n "$GENRES" -o -n "$COUNTRIES" -o -n "$CASTMEMBERS" -o -n "$CATEGORY" ]
  1031.     then
  1032.         VIDID=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1033.         select intid from videometadata where filename = "$FILENAME";
  1034.         EOF
  1035.         )
  1036.     fi
  1037.     if [ -n "$VIDID" ]
  1038.     then
  1039.         if [ -n "$GENRES" ]
  1040.         then
  1041.             scriptlog DEBUG "Will check for genres $GENRES"
  1042.             OLDIFS="$IFS"; IFS=','; set - $GENRES; IFS="$OLDIFS"
  1043.             for GENRE in "$@"
  1044.             do
  1045.                 ID=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1046.                 select intid from videogenre where lcase(genre) = lcase("${GENRE}");
  1047.                 EOF
  1048.                 )
  1049.                 if [ -z "$ID" ]
  1050.                 then
  1051.                     [ "$DEBUGSQL" = "ON" ] && echo "insert into videogenre set genre = ${GENRE}"
  1052.                     mysql --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1053.                     insert into videogenre set genre = "${GENRE}";
  1054.                     EOF
  1055.                     ID=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1056.                     select intid from videogenre where lcase(genre) = lcase("${GENRE}");
  1057.                     EOF
  1058.                     )
  1059.                 fi
  1060.                 if [ -n "$ID" ]
  1061.                 then
  1062.                     TMP=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1063.                     select idvideo from videometadatagenre where idvideo = $VIDID and idgenre = $ID;
  1064.                     EOF
  1065.                     )
  1066.                     if [ -z "$TMP" ]
  1067.                     then
  1068.                         [ "$DEBUGSQL" = "ON" ] && echo "insert into videometadatagenre set idvideo = $VIDID, idgenre = $ID - $GENRE"
  1069.                         mysql --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1070.                         insert into videometadatagenre set idvideo = $VIDID, idgenre = $ID;
  1071.                         EOF
  1072.                         scriptlog INFO "Adding to genre $GENRE"
  1073.                     fi
  1074.                 fi
  1075.             done
  1076.         fi
  1077.  
  1078.         if [ -n "$COUNTRIES" ]
  1079.         then
  1080.             scriptlog DEBUG "Will check for countries $COUNTRIES"
  1081.             OLDIFS="$IFS"; IFS=','; set - $COUNTRIES; IFS="$OLDIFS"
  1082.             for COUNTRY in "$@"
  1083.             do
  1084.                 ID=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1085.                 select intid from videocountry where lcase(country) = lcase("${COUNTRY}");
  1086.                 EOF
  1087.                 )
  1088.                 if [ -z "$ID" ]
  1089.                 then
  1090.                     [ "$DEBUGSQL" = "ON" ] && echo "insert into videocountry set country = ${COUNTRY}"
  1091.                     mysql --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1092.                     insert into videocountry set country = "${COUNTRY}";
  1093.                     EOF
  1094.                     ID=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1095.                     select intid from videocountry where lcase(country) = lcase("${COUNTRY}");
  1096.                     EOF
  1097.                     )
  1098.                 fi
  1099.                 if [ -n "$ID" ]
  1100.                 then
  1101.                     TMP=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1102.                     select idvideo from videometadatacountry where idvideo = $VIDID and idcountry = $ID;
  1103.                     EOF
  1104.                     )
  1105.                     if [ -z "$TMP" ]
  1106.                     then
  1107.                         [ "$DEBUGSQL" = "ON" ] && echo "insert into videometadatacountry set idvideo = $VIDID, idcountry = $ID - $COUNTRY"
  1108.                         mysql --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1109.                         insert into videometadatacountry set idvideo = $VIDID, idcountry = $ID;
  1110.                         EOF
  1111.                         scriptlog INFO "Adding to country $COUNTRY"
  1112.                     fi
  1113.                 fi
  1114.             done
  1115.         fi
  1116.  
  1117.         if [ -n "$CASTMEMBERS" ]
  1118.         then
  1119.             scriptlog DEBUG "Will check for cast $CASTMEMBERS"
  1120.             OLDIFS="$IFS"; IFS=","; set - $CASTMEMBERS; IFS="$OLDIFS"
  1121.             for CAST in "$@"
  1122.             do
  1123.                 ID=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1124.                 select intid from videocast where lcase(cast) = lcase("${CAST}");
  1125.                 EOF
  1126.                 )
  1127.                 if [ -z "$ID" ]
  1128.                 then
  1129.                     [ "$DEBUGSQL" = "ON" ] && echo "insert into videocast set cast = ${CAST}"
  1130.                     mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1131.                     insert into videocast set cast = "${CAST}";
  1132.                     EOF
  1133.                     ID=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1134.                     select intid from videocast where lcase(cast) = lcase("${CAST}");
  1135.                     EOF
  1136.                     )
  1137.                 fi
  1138.                 if [ -n "$ID" ]
  1139.                 then
  1140.                     TMP=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1141.                     select idvideo from videometadatacast where idvideo = $VIDID and idcast = $ID;
  1142.                     EOF
  1143.                     )
  1144.                     if [ -z "$TMP" ]
  1145.                     then
  1146.                         [ "$DEBUGSQL" = "ON" ] && echo "insert into videometadatacast set idvideo = $VIDID, idcast = $ID - $CAST"
  1147.                         mysql --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1148.                         insert into videometadatacast set idvideo = $VIDID, idcast = $ID;
  1149.                         EOF
  1150.                         scriptlog INFO "Adding cast member $CAST"
  1151.                     fi
  1152.                 fi
  1153.             done
  1154.         fi
  1155.  
  1156.         if [ -n "$CATEGORY" ]
  1157.         then
  1158.             CATEGORY=$(echo "$CATEGORY" | tr -d ' ')
  1159.             OLDIFS="$IFS"; IFS='/'; set - $CATEGORY; IFS="$OLDIFS"
  1160.             for CAT in "$@"
  1161.             do
  1162.                 # Use mappings
  1163.                 [ -n "${mythcat[$CAT]}" ] && CAT=${mythcat[$CAT]}
  1164.                 [ "$DEBUGSQL" = "ON" ] && echo "select intid from videocategory where lcase(category) = lcase(${CAT})"
  1165.                 ID=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1166.                 select intid from videocategory where lcase(category) = lcase("${CAT}");
  1167.                 EOF
  1168.                 )
  1169.                 if [ -n "$ID" ]
  1170.                 then
  1171.                     [ "$DEBUGSQL" = "ON" ] && echo "update videometadata set category = $ID where intid = $VIDID"
  1172.                     mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1173.                     update videometadata set category = $ID where intid = $VIDID;
  1174.                     EOF
  1175.                     scriptlog INFO "Added to category $CAT"
  1176.                     break # only 1 category
  1177.                 else
  1178.                     scriptlog INFO "Category $CAT does not exist"
  1179.                 fi
  1180.             done
  1181.         fi
  1182.     fi
  1183.     return 0
  1184. }
  1185.  
  1186. hasvideometadata() {
  1187. local FILENAME="$1"
  1188. local DATA
  1189.     DATA=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1190.     select intid from videometadata where filename = "$FILENAME";
  1191.     EOF
  1192.     )
  1193.     echo $DATA | grep '^[0-9][0-9][0-9]*$' >/dev/null 2>&1 && return 0 || return 1
  1194. }
  1195.  
  1196. deleterecording() {
  1197. local CHANID="$1"
  1198. local STARTTIME="$2"
  1199.     [ -n "$CHANID" ] || return 1
  1200.     mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1201.     update recorded set recgroup = "Deleted", autoexpire = 999 where chanid = $CHANID and starttime = "$STARTTIME";
  1202.     EOF
  1203. }
  1204.  
  1205. insertmythlogentry() {
  1206. local PRIORITY="$1"
  1207. local LEVEL="$2"
  1208. local PID="$3"
  1209. local DETAILS="$(echo $4 | tr -d '[:cntrl:]' | tr -d '[\\\"]')"
  1210. local DATETIME=$(date '+%Y%m%d%H%M%S')
  1211. local HOST=$(hostname)
  1212.     mysql --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1213.     insert into mythlog set
  1214.     module = "mythnuv2mkv.sh",
  1215.     priority = $PRIORITY,
  1216.     acknowledged = 0,
  1217.     logdate = $DATETIME,
  1218.     host = "$HOST",
  1219.     message = "mythnuv2mkv.sh [$PID] $LEVEL",
  1220.     details = "$DETAILS";
  1221.     EOF
  1222. }
  1223.  
  1224. getjobqueuecmds() {
  1225. local JOBID="$1"
  1226. local DATA
  1227. local JQCMDSTR[0]="RUN"
  1228. local JQCMDSTR[1]="PAUSE"
  1229. local JQCMDSTR[2]="RESUME"
  1230. local JQCMDSTR[4]="STOP"
  1231. local JQCMDSTR[8]="RESTART"
  1232.     DATA=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1233.     select cmds from jobqueue where id = $JOBID;
  1234.     EOF
  1235.     )
  1236.     echo ${JQCMDSTR[$DATA]}
  1237. }
  1238.  
  1239. setjobqueuecmds() {
  1240. local JOBID="$1"
  1241. local CMDSSTR="$2"
  1242. local CMDS
  1243.     if echo "$CMDSSTR" | egrep '^[0-9]+$' >/dev/null 2>&1
  1244.     then
  1245.         CMDS=$CMDSSTR
  1246.     elif [ "$CMDSSTR" = "RUN" ]
  1247.     then
  1248.         CMDS=0
  1249.     fi
  1250.     if [ -n "$CMDS" ]
  1251.     then
  1252.         mysql --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1253.         update jobqueue set cmds = $CMDS where id = $JOBID;
  1254.         EOF
  1255.     else
  1256.         scriptlog ERROR "Invalid Job Queue Command."
  1257.     fi
  1258. }
  1259.  
  1260. getjobqueuestatus() {
  1261. local JOBID="$1"
  1262. local DATA
  1263. local JQSTATUSSTR[0]="UNKNOWN"
  1264. local JQSTATUSSTR[1]="QUEUED"
  1265. local JQSTATUSSTR[2]="PENDING"
  1266. local JQSTATUSSTR[3]="STARTING"
  1267. local JQSTATUSSTR[4]="RUNNING"
  1268. local JQSTATUSSTR[5]="STOPPING"
  1269. local JQSTATUSSTR[6]="PAUSED"
  1270. local JQSTATUSSTR[7]="RETRY"
  1271. local JQSTATUSSTR[8]="ERRORING"
  1272. local JQSTATUSSTR[9]="ABORTING"
  1273. local JQSTATUSSTR[256]="DONE"
  1274. local JQSTATUSSTR[272]="FINISHED"
  1275. local JQSTATUSSTR[288]="ABORTED"
  1276. local JQSTATUSSTR[304]="ERRORED"
  1277. local JQSTATUSSTR[320]="CANCELLED"
  1278.     DATA=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1279.     select status from jobqueue where id = $JOBID;
  1280.     EOF
  1281.     )
  1282.     echo ${JQSTATUSSTR[$DATA]}
  1283. }
  1284.  
  1285. setjobqueuestatus() {
  1286. local JOBID="$1"
  1287. local STATUSSTR="$2"
  1288. local STATUS
  1289.     if echo "$STATUSSTR" | egrep '^[0-9]+$' >/dev/null 2>&1
  1290.     then
  1291.         STATUS=$STATUSSTR
  1292.     elif [ "$STATUSSTR" = "RUNNING" ]
  1293.     then
  1294.         STATUS=4
  1295.     elif [ "$STATUSSTR" = "PAUSED" ]
  1296.     then
  1297.         STATUS=6
  1298.     elif [ "$STATUSSTR" = "ABORTING" ]
  1299.     then
  1300.         STATUS=9
  1301.     elif [ "$STATUSSTR" = "FINISHED" ]
  1302.     then
  1303.         STATUS=272
  1304.     elif [ "$STATUSSTR" = "ERRORED" ]
  1305.     then
  1306.         STATUS=304
  1307.     fi
  1308.     if [ -n "$STATUS" ]
  1309.     then
  1310.         mysql --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1311.         update jobqueue set status = $STATUS where id = $JOBID;
  1312.         EOF
  1313.     else
  1314.         scriptlog ERROR "Invalid Job Queue Status."
  1315.     fi
  1316. }
  1317.  
  1318. getjobqueuecomment() {
  1319. local JOBID="$1"
  1320. local COMMENT="$2"
  1321.     mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1322.     select comment from jobqueue where id = $JOBID;
  1323.     EOF
  1324. }
  1325.  
  1326. setjobqueuecomment() {
  1327. local JOBID="$1"
  1328. local COMMENT="$2"
  1329.     mysql --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1330.     update jobqueue set comment = "$COMMENT" where id = $JOBID;
  1331.     EOF
  1332. }
  1333.  
  1334. # My channelprofiles table for setting aspect at channel level.
  1335. # See http://web.aanet.com.au/auric/?q=node/1
  1336. # You probably don't have it.
  1337. getchannelaspect() {
  1338. local CHANID=$1
  1339. local DATA
  1340.     {
  1341.     DATA=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1342.     select aspectratio from channelprofiles
  1343.         where channum = (select channum from channel where chanid = $CHANID)
  1344.         and sourceid = (select sourceid from channel where chanid = $CHANID);
  1345.     EOF
  1346.     )
  1347.     case $DATA in
  1348.         16:9|4:3) true ;;
  1349.         '') DATA=$DEFAULTMPEG2ASPECT ;;
  1350.         *) DATA=NA ;;
  1351.     esac
  1352.     } >/dev/null 2>&1
  1353.     echo $DATA
  1354. }
  1355.  
  1356. # aspect ratio of the V4L or MPEG capture card associated with CHANID
  1357. # No good for any other type of card. e.g. DVB.
  1358. querycardaspect() {
  1359. local CHANID=$1
  1360. local DATA
  1361.     DATA=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  1362.     select value from codecparams where name = 'mpeg2aspectratio'
  1363.     and profile = (select id from recordingprofiles where name = 'default'
  1364.         and profilegroup = (select id from profilegroups
  1365.             where cardtype = (select cardtype from capturecard
  1366.                 where cardid = (select cardid from cardinput
  1367.                     where sourceid = (select sourceid from channel
  1368.                         where chanid = $CHANID)
  1369.                     )
  1370.                 )
  1371.             )
  1372.         );
  1373.     EOF
  1374.     )
  1375.     [ "$DATA" != "4:3" -a "$DATA" != "16:9" ] && DATA="NA"
  1376.     echo $DATA
  1377. }
  1378.  
  1379. getaviinfomidentify() {
  1380. local FILE="$1"
  1381. local ATRACK="$2"
  1382. shift 2
  1383. local PROPS="$@"
  1384. local MPOP
  1385. local TMP
  1386. local p
  1387. local RES
  1388. local ASPECTFOUNDIN
  1389. local width=1           ; infokey[1]="ID_VIDEO_WIDTH"
  1390. local height=2          ; infokey[2]="ID_VIDEO_HEIGHT"
  1391. local fps=3         ; infokey[3]="ID_VIDEO_FPS"
  1392. local audio_sample_rate=4   ; infokey[4]="ID_AUDIO_RATE"
  1393. local audio_channels=5      ; infokey[5]="ID_AUDIO_NCH"
  1394. local aspect=6          ; infokey[6]="ID_VIDEO_ASPECT"
  1395. local length=7          ; infokey[7]="ID_LENGTH"
  1396. local video_format=8        ; infokey[8]="ID_VIDEO_FORMAT"
  1397. local audio_format=9        ; infokey[9]="ID_AUDIO_CODEC"
  1398.     ATRACK_PID=$(mplayer -really-quiet -nojoystick -nolirc -nomouseinput -vo null -ao null -frames 0 -identify "$FILE" 2>/dev/null | \
  1399.         awk -F"=" "/ID_AUDIO_ID=([0-9]+)/ { if ( x++ == $ATRACK ) print \$2 }")
  1400.     MPOP=$(mplayer -aid ${ATRACK_PID} -really-quiet -nojoystick -nolirc -nomouseinput -vo null -ao null -frames 0 -identify "$FILE" 2>/dev/null)
  1401.     for p in $PROPS
  1402.     do
  1403.         [ -n "${infokey[$p]}" ] && p=${infokey[$p]}
  1404.         case $p in
  1405.             "scan_type")
  1406.                 TMP="NA"
  1407.             ;;
  1408.             "finfo")
  1409.                 TMP="NA"
  1410.             ;;
  1411.             "audio_bitrate")
  1412.                 TMP="NA"
  1413.             ;;
  1414.             "audio_resolution")
  1415.                 TMP="NA"
  1416.             ;;
  1417.             "audio_language")
  1418.                 TMP="NA"
  1419.             ;;
  1420.             "ID_VIDEO_ASPECT")
  1421.                 TMP="$(echo "$MPOP" | awk -F'=' '/ID_VIDEO_ASPECT/ {if($2>1.1 && $2<1.5)print "4:3";if($2>1.6 && $2<2)print "16:9"}')"
  1422.                 [ "$TMP" != "4:3" -a "$TMP" != "16:9" ] && TMP="NA"
  1423.                 ASPECTFOUNDIN="File"
  1424.                 if [ "$TMP" = "NA" -a ${FILE##*.} = "mpg" -a -n "$CHANID" ]
  1425.                 then
  1426.                     TMP=$(getchannelaspect $CHANID)
  1427.                     ASPECTFOUNDIN="Channel"
  1428.                 fi
  1429.                 if [ "$TMP" = "NA" -a ${FILE##*.} = "mpg" -a -n "$CHANID" ]
  1430.                 then
  1431.                     TMP=$(querycardaspect $CHANID)
  1432.                     ASPECTFOUNDIN="Card"
  1433.                 fi
  1434.                 if [ "$TMP" = "NA" -a ${FILE##*.} = "mpg" ]
  1435.                 then
  1436.                     TMP=$DEFAULTMPEG2ASPECT
  1437.                     ASPECTFOUNDIN="Default"
  1438.                 fi
  1439.                 TMP="$TMP,$ASPECTFOUNDIN"
  1440.             ;;
  1441.             "ID_VIDEO_HEIGHT")
  1442.                 TMP="$(echo "$MPOP" | grep $p | tail -1 | cut -d'=' -f2)"
  1443.                 [ "$TMP" = "1080" ] && TMP="1088" # HD FIX
  1444.             ;;
  1445.             "ID_VIDEO_FORMAT")
  1446.                 TMP="$(echo "$MPOP" | grep $p | tail -1 | cut -d'=' -f2)"
  1447.                 case "$TMP" in
  1448.                     "0x10000002") TMP="MPEG" ;;
  1449.                     "avc1") TMP="AVC" ;;
  1450.                     "MPEG-4 Visual") TMP="MPEG4" ;;
  1451.                     "FMP4") TMP="MPEG4" ;;
  1452.                     "DX50") TMP="DIVX" ;;
  1453.                     "H264") TMP="H264" ;;
  1454.                 esac
  1455.             ;;
  1456.             *)
  1457.                 TMP="$(echo "$MPOP" | grep $p | tail -1 | cut -d'=' -f2)"
  1458.             ;;
  1459.         esac
  1460.         [ -z "$RES" ] && RES="$TMP" || RES="${RES}:${TMP}"
  1461.     done
  1462.     echo "$RES"
  1463. }
  1464.  
  1465. getaviinfomediainfo() {
  1466. local FILE="$1"
  1467. local ATRACK="$2"
  1468. shift
  1469. local PROPS="$@"
  1470. local TMP
  1471. local p
  1472. local RES
  1473. local ASPECTFOUNDIN
  1474.     for p in $PROPS
  1475.     do
  1476.         TMP=""
  1477.         case "$p" in
  1478.             "aspect")
  1479.                 TMP=$(mediainfo --Inform="Video;%DisplayAspectRatio/String%" "$FILE")
  1480.                 if [ "$TMP" = "4:3" -o "$TMP" = "4/3" ]
  1481.                 then
  1482.                     ASPECTFOUNDIN="File"
  1483.                 elif [ "$TMP" = "16:9" -o "$TMP" = "16/9" ]
  1484.                 then
  1485.                     ASPECTFOUNDIN="File"
  1486.                 else
  1487.                     TMP="NA"
  1488.                 fi
  1489.  
  1490.                 if [ "$TMP" = "NA" -a ${FILE##*.} = "mpg" -a -n "$CHANID" ]
  1491.                 then
  1492.                     TMP=$(getchannelaspect $CHANID)
  1493.                     ASPECTFOUNDIN="Channel"
  1494.                 fi
  1495.                 if [ "$TMP" = "NA" -a ${FILE##*.} = "mpg" -a -n "$CHANID" ]
  1496.                 then
  1497.                     TMP=$(querycardaspect $CHANID)
  1498.                     ASPECTFOUNDIN="Card"
  1499.                 fi
  1500.                 if [ "$TMP" = "NA" -a ${FILE##*.} = "mpg" ]
  1501.                 then
  1502.                     TMP=$DEFAULTMPEG2ASPECT
  1503.                     ASPECTFOUNDIN="Default"
  1504.                 fi
  1505.                 [ -z "$TMP" ] && TMP=$(getaviinfomidentify "$FILE" $ATRACK "$p")
  1506.                 TMP="$TMP,$ASPECTFOUNDIN"
  1507.             ;;
  1508.             "height")
  1509.                 TMP=$(mediainfo --Inform="Video;%Height%" "$FILE")
  1510.                 [ -z "$TMP" ] && TMP=$(getaviinfomidentify "$FILE" $ATRACK "$p")
  1511.                 [ "$TMP" = "1080" ] && TMP="1088" # HD FIX
  1512.             ;;
  1513.             "audio_sample_rate")
  1514.                 TMP=$(mediainfo --Inform="Audio;%SamplingRate/String%\n" "$FILE" | awk "{ if ( x++ == $ATRACK ) print \$1 * 1000 }")
  1515.                 [ -z "$TMP" ] && TMP=$(getaviinfomidentify "$FILE" $ATRACK "$p")
  1516.             ;;
  1517.             "Duration")
  1518.                 TMP=$(mediainfo --Inform="Video;%Duration%" "$FILE")
  1519.             ;;
  1520.             "video_format")
  1521.                 TMP=$(getaviinfomidentify "$FILE" video_format)
  1522.                 [ -z "$TMP" ] && TMP=$(getaviinfomidentify "$FILE" $ATRACK "$p")
  1523.             ;;
  1524.             "width")
  1525.                 TMP=$(mediainfo --Inform="Video;%Width%" "$FILE")
  1526.                 [ -z "$TMP" ] && TMP=$(getaviinfomidentify "$FILE" $ATRACK "$p")
  1527.             ;;
  1528.             "fps")
  1529.                 TMP=$(mediainfo --Inform="Video;%FrameRate%" "$FILE")
  1530.                 [ -z "$TMP" ] && TMP=$(getaviinfomidentify "$FILE" $ATRACK "$p")
  1531.             ;;
  1532.             "audio_channels")
  1533.                 TMP=$(mediainfo --Inform="Audio;%Channel(s)/String%\n" "$FILE" | awk "{ if ( x++ == $ATRACK ) print \$1 }")
  1534.                 [ -z "$TMP" ] && TMP=$(getaviinfomidentify "$FILE" $ATRACK "$p")
  1535.             ;;
  1536.             "audio_bitrate")
  1537.                 TMP=$(mediainfo --Inform="Audio;%BitRate/String%\n" "$FILE" | awk "{ if ( x++ == $ATRACK ) print \$1 }")
  1538.                 [ -z "$TMP" ] && TMP="NA"
  1539.             ;;
  1540.             "audio_resolution")
  1541.                 TMP=$(mediainfo --Inform="Audio;%Resolution/String%\n" "$FILE" | awk "{ if ( x++ == $ATRACK ) print \$1 }")
  1542.                 [ -z "$TMP" ] && TMP="NA"
  1543.             ;;
  1544.             "scan_type")
  1545.                 TMP=$(mediainfo --Inform="Video;%ScanType%" "$FILE")
  1546.                 [ "$TMP" = "MBAFF" ] && TMP="Interlaced"
  1547.                 [ -z "$TMP" ] && TMP="NA"
  1548.             ;;
  1549.             "audio_language")
  1550.                 TMP=$(mediainfo --Inform="Audio;%Language/String3%\n" "$FILE" | awk "{ if ( x++ == $ATRACK ) print \$1 }")
  1551.                 [ -z "$TMP" ] && TMP="NA"
  1552.             ;;
  1553.             "audio_format")
  1554.                 TMP=$(mediainfo --Inform="Audio;%Format%\n" "$FILE" | awk "{ if ( x++ == $ATRACK ) print \$1 }")
  1555.                 [ -z "$TMP" ] && TMP="NA"
  1556.             ;;
  1557.         esac
  1558.         [ -z "$RES" ] && RES="$TMP" || RES="${RES}:${TMP}"
  1559.     done
  1560.     echo "$RES"
  1561. }
  1562.  
  1563. getnuvinfo() {
  1564. export NUVINFOFILE="$1"
  1565. shift
  1566. export NUVINFOPROPS="$@"
  1567.     PROPS=$(sed -n '/^#STARTNUVINFO$/,/#ENDNUVINFO/p' $CMD | perl)
  1568.     echo "$PROPS"
  1569. }
  1570.  
  1571. getvidinfo() {
  1572. local FILE="$1"
  1573. local ATRACK="$2"
  1574. shift 2
  1575. local PROPS="$@"
  1576. local RES
  1577.     if echo "$FILE" | grep '\.nuv' >/dev/null 2>&1
  1578.     then   
  1579.         RES=$(getnuvinfo "$FILE" $PROPS)
  1580.     else
  1581.         if [ "$USEMEDIAINFO" = "TRUE" ] && which mediainfo >/dev/null 2>&1
  1582.         then
  1583.             RES=$(getaviinfomediainfo "$FILE" $ATRACK $PROPS)
  1584.         else
  1585.             RES=$(getaviinfomidentify "$FILE" $ATRACK $PROPS)
  1586.         fi
  1587.     fi
  1588.     echo "$RES"
  1589. }
  1590.  
  1591. getaspect() {
  1592. local FILE="$1"
  1593. local ASPECT="NA"
  1594.     ASPECT=$(getvidinfo "$FILE" 0 aspect)
  1595.     ASPECT=$(echo $ASPECT | sed -e 's/\./:/')
  1596.     echo "$ASPECT" | grep ',' >/dev/null 2>&1 || ASPECT="$ASPECT,File"
  1597.     echo "$ASPECT"
  1598. }
  1599.  
  1600. getlengthffmpeg() {
  1601. FILE="$1"
  1602. local LENGTH=""
  1603.     LENGTH=$(ffmpeg -i "$FILE" 2>&1 | awk -F'[:.]' '/Duration: / {print $2 * 3600 + $3 * 60 + $4}')
  1604.     echo "$LENGTH" | grep '^[0-9][0-9]*$'
  1605. }
  1606.  
  1607. getlength() {
  1608. FILE="$1"
  1609. local LENGTH=""
  1610.     LENGTH=$(getaviinfomidentify "$FILE" 0 length)
  1611.     if [ -z "$LENGTH" -o "$LENGTH" -lt 1 ]
  1612.     then
  1613.         scriptlog DEBUG "getaviinfomidentify failed length $LENGTH"
  1614.         LENGTH=$(getlengthffmpeg "$FILE")
  1615.         if [ -z "$LENGTH" -a "$LENGTH" -lt 0 ]
  1616.         then
  1617.             scriptlog DEBUG "getlengthffmpeg failed length $LENGTH"
  1618.             return 1
  1619.         fi
  1620.     fi
  1621.     echo $LENGTH
  1622. }
  1623.  
  1624. # save value $2 in variable $1, optionally saving the original value into \$SAVED$1
  1625. setsave() {
  1626.     local VARNAME=$1
  1627.     local SAVED="SAVED${VARNAME}"
  1628.     local VALUE=$2
  1629.     local SAVE=$3
  1630.     scriptlog DEBUG SetSaving "$VARNAME=$VALUE (old: ${!VARNAME}, save: $SAVE)"
  1631.     # only save once, and only if changed
  1632.     [ -n "$SAVE" -a -z "${!SAVED}" -a "${!VARNAME}" != "$VALUE" ] && eval "$SAVED=\"${!VARNAME}\""
  1633.     # forget old saved value
  1634.     [ -z "$SAVE" ] && eval "$SAVED="
  1635.     eval "${VARNAME}=\"${VALUE}\""
  1636. }
  1637.  
  1638. # recall saved value of variable $1, if available
  1639. recall() {
  1640.     if [ -z "$@" ]
  1641.     then
  1642.         for VARNAME in $RECALL
  1643.         do
  1644.             recall $VARNAME
  1645.         done
  1646.         for VARNAME in $CLEAN
  1647.         do
  1648.             eval "$VARNAME="
  1649.         done
  1650.     else
  1651.         local VARNAME=$1
  1652.         local SAVED="SAVED${VARNAME}"
  1653.         if [ -n "${!SAVED}" ]
  1654.         then
  1655.             scriptlog DEBUG "Recalling $VARNAME from ${!VARNAME}, saved ${!SAVED}"
  1656.             eval "${VARNAME}=\"${!SAVED}\""
  1657.             eval "${SAVED}="
  1658.         fi
  1659.     fi
  1660. }
  1661.  
  1662. setaspect() {
  1663.     setsave ASPECTINLINE "$1" "$2"
  1664. }
  1665.  
  1666. setdenoise() {
  1667.     setsave DENOISE "$(echo $1 | tr '[a-z]' '[A-Z]')" "$2"
  1668.     if echo "$DENOISE" | egrep -i 'ON|YES' >/dev/null 2>&1
  1669.     then
  1670.         setsave POSTVIDFILTERS "${POSTVIDFILTERS}${DENOISEFILTER}," "$2"
  1671.         scriptlog INFO "Denoise filter added."
  1672.     else
  1673.         setsave POSTVIDFILTERS "$(echo ${POSTVIDFILTERS} | sed -e 's/'${DENOISEFILTER}',//')" "$2"
  1674.         scriptlog INFO "Denoise filter removed."
  1675.     fi
  1676. }
  1677.  
  1678. setdeblock() {
  1679.     setsave DEBLOCK "$(echo $1 | tr '[a-z]' '[A-Z]')" "$2"
  1680.     if echo "$DEBLOCK" | egrep -i 'ON|YES' >/dev/null 2>&1
  1681.     then
  1682.         setsave POSTVIDFILTERS "${POSTVIDFILTERS}${DEBLOCKFILTER}," "$2"
  1683.         scriptlog INFO "Deblock filter added."
  1684.     else
  1685.         setsave POSTVIDFILTERS "$(echo ${POSTVIDFILTERS} | sed -e 's/'${DEBLOCKFILTER}',//')" "$2"
  1686.         scriptlog INFO "Deblock filter removed."
  1687.     fi
  1688. }
  1689.  
  1690. setdeinterlace() {
  1691.     setsave DEINTERLACE "$(echo $1 | tr '[a-z]' '[A-Z]')" "$2"
  1692.     if echo "$DEINTERLACE" | egrep -i 'ON|YES' >/dev/null 2>&1
  1693.     then
  1694.         scriptlog INFO "Deinterlace filter made available."
  1695.     else
  1696.         scriptlog INFO "Deinterlace filter made unavailable."
  1697.     fi
  1698. }
  1699.  
  1700. setinvtelecine() {
  1701.     setsave INVTELECINE "$(echo "$1" | tr '[a-z]' '[A-Z]')" "$2"
  1702.     if echo "$INVTELECINE" | egrep -i 'ON|YES' >/dev/null 2>&1
  1703.     then
  1704.         scriptlog INFO "Invtelecine filter made available."
  1705.     else
  1706.         scriptlog INFO "Invtelecine filter made unavailable."
  1707.     fi
  1708. }
  1709.  
  1710. setcrop() {
  1711.     setsave CROP $(echo "$1" | tr '[a-z]' '[A-Z]') "$2"
  1712.     if echo "$CROP" | egrep '[0-9]+' >/dev/null 2>&1
  1713.     then
  1714.         setsave CROPSIZE "$CROP" "$2"
  1715.         setsave CROP "ON" "$2"
  1716.         scriptlog INFO "Cropping $CROPSIZE pixels from each side"
  1717.         [ $(( ($CROPSIZE*2) % 16 )) -ne 0 ] && scriptlog WARN "WARNING Crop sizes NOT a multiple of 16. This is bad"
  1718.     elif [ "$CROP" = "ON" ]
  1719.     then
  1720.         scriptlog INFO "Cropping $CROPSIZE pixels from each side"
  1721.     else
  1722.         scriptlog INFO "Crop set $CROP."
  1723.     fi
  1724. }
  1725.  
  1726. setdeleterec() {
  1727.     setsave DELETEREC "$(echo "$1" | tr '[a-z]' '[A-Z]')" "$2"
  1728.     scriptlog INFO "Delete Recording set to $DELETEREC."
  1729. }
  1730.  
  1731. setchapterduration() {
  1732.     setsave CHAPTERDURATION "$1" "$2"
  1733.     scriptlog INFO "Chapter Duration set to $CHAPTERDURATION."
  1734. }
  1735.  
  1736. setchapterfile() {
  1737.     setsave CHAPTERFILE "$1" "$2"
  1738.     if [ -f "$CHAPTERFILE" ]
  1739.     then
  1740.         scriptlog INFO "Chapter File set to $CHAPTERFILE."
  1741.     else
  1742.         setsave CHAPTERFILE "" "$2"
  1743.         scriptlog ERROR "Chapter File $CHAPTERFILE not found."
  1744.     fi
  1745. }
  1746.  
  1747. setcopydir() {
  1748.     setsave COPYDIR "$1" "$2"
  1749.     if [ ! -d "$COPYDIR" -o ! -w "$COPYDIR" ] && ! mkdir -p "$COPYDIR"
  1750.     then
  1751.         scriptlog ERROR "$COPYDIR does not exist and cannot be created or is not writable. Continuing but result will be left in source directory unless $COPYDIR is created before job completes."
  1752.         return 1
  1753.     else
  1754.         scriptlog INFO "Video will be located in $COPYDIR."
  1755.         return 0
  1756.     fi 
  1757. }
  1758.  
  1759. setcontype() {
  1760.     local TMP=$(echo "$1" | tr '[A-Z]' '[a-z]')
  1761.     local SAVE=$2
  1762.     local OLDIFS="$IFS"; IFS=","; set - $TMP; IFS="$OLDIFS"
  1763.     local TMP1="$1" ; local TMP2="$2"
  1764.     if [ "$TMP1" = "mp4" ]
  1765.     then
  1766.         if [ -n "$CHANID" -a -z "$COPYDIR" ]
  1767.         then
  1768.             setsave CONTYPE "avi" "$SAVE"
  1769.             setsave QUICKTIME_MP4 "NO" "$SAVE"
  1770.             scriptlog ERROR "Changed to $TMP1 failed. mp4 not supported in MythRecord."
  1771.         elif ! chkreqs "$MP4REQPROGS" "$MP4REQLIBS"
  1772.         then
  1773.             scriptlog ERROR "Changed to $TMP1 failed. Missing Requirements."
  1774.             exit $FINALEXIT
  1775.         else
  1776.             setsave CONTYPE "mp4" "$SAVE"
  1777.             setsave QUICKTIME_MP4 "NO" "$SAVE"
  1778.             scriptlog INFO "Changed to $CONTYPE."
  1779.         fi
  1780.     elif [ "$TMP1" = "mov" ]
  1781.     then
  1782.         if [ -n "$CHANID" -a -z "$COPYDIR" ]
  1783.         then
  1784.             setsave CONTYPE "avi" "$SAVE"
  1785.             setsave QUICKTIME_MP4 "NO" "$SAVE"
  1786.             scriptlog ERROR "Changed to $TMP1 failed. mov not supported in MythRecord."
  1787.         elif ! chkreqs "$MP4REQPROGS" "$MP4REQLIBS"
  1788.         then
  1789.             scriptlog ERROR "Changed to $TMP1 failed. Missing Requirements."
  1790.             exit $FINALEXIT
  1791.         else
  1792.             setsave CONTYPE "mp4" "$SAVE"
  1793.             setsave QUICKTIME_MP4 "YES" "$SAVE"
  1794.             scriptlog INFO "Changed to $CONTYPE (mov)."
  1795.         fi
  1796.     elif [ "$TMP1" = "mkv" ]
  1797.     then
  1798.         if [ -n "$CHANID" -a -z "$COPYDIR" ]
  1799.         then
  1800.             setsave CONTYPE "avi" "$SAVE"
  1801.             setsave QUICKTIME_MP4 "NO" "$SAVE"
  1802.             scriptlog ERROR "Changed to $TMP1 failed. mkv not supported in MythRecord."
  1803.         elif ! chkreqs "$MKVREQPROGS" "$MKVREQLIBS"
  1804.         then
  1805.             scriptlog ERROR "Changed to $TMP1 failed. Missing Requirements."
  1806.             exit $FINALEXIT
  1807.         else
  1808.             setsave CONTYPE "mkv" "$SAVE"
  1809.             setsave QUICKTIME_MP4 "NO" "$SAVE"
  1810.             [ "$TMP2" = "ogg" ] && setsave MKVAUD "ogg" "$SAVE"
  1811.             [ "$TMP2" = "acc" ] && setsave MKVAUD "acc" "$SAVE"
  1812.             scriptlog INFO "Changed to ${CONTYPE},${MKVAUD}."
  1813.         fi
  1814.     elif [ "$TMP1" = "avi" ]
  1815.     then
  1816.         if ! chkreqs "$AVIREQPROGS" "$AVIREQLIBS"
  1817.         then
  1818.             scriptlog ERROR "Changed to $TMP1 failed. Missing Requirements."
  1819.             exit $FINALEXIT
  1820.         else
  1821.             setsave CONTYPE "avi" "$SAVE"
  1822.             setsave QUICKTIME_MP4 "NO" "$SAVE"
  1823.             [ "$TMP2" = "xvid" ] && setsave AVIVID "xvid" "$SAVE"
  1824.             [ "$TMP2" = "lavc" ] && setsave AVIVID "lavc" "$SAVE"
  1825.             [ "$TMP2" = "divx" ] && setsave AVIVID "lavc" "$SAVE"
  1826.             scriptlog INFO "Changed to ${CONTYPE},${AVIVID}."
  1827.         fi
  1828.     else
  1829.         scriptlog ERROR "Changed to $TMP1 failed. Invalid contype."
  1830.     fi
  1831. }
  1832.  
  1833. setpass() {
  1834.     TMP=$(echo "$1" | tr '[A-Z]' '[a-z]')
  1835.     if [ "$TMP" = "one" -o "$TMP" = "1" ]
  1836.     then
  1837.         scriptlog INFO "Changed to $TMP pass."
  1838.         setsave PASS "one" "$2"
  1839.     elif [ "$TMP" = "two" -o "$TMP" = "2" ]
  1840.     then
  1841.         scriptlog INFO "Changed to $TMP pass."
  1842.         setsave PASS "two" "$2"
  1843.     else
  1844.         scriptlog ERROR "Changed to $TMP failed. Invalid value for pass."
  1845.     fi
  1846. }
  1847.  
  1848. setquality() {
  1849.     QLEVEL=$1
  1850.     SAVE=$2
  1851.     if echo "$QLEVEL" | grep -i "high" >/dev/null 2>&1
  1852.     then
  1853.         setsave SCALE43 $HIGH_SCALE43 "$SAVE"
  1854.         setsave SCALE169 $HIGH_SCALE169 "$SAVE"
  1855.         setsave LAVC_CQ $HIGH_LAVC_CQ "$SAVE"
  1856.         setsave LAVC_OPTS $HIGH_LAVC_OPTS "$SAVE"
  1857.         setsave XVID_CQ $HIGH_XVID_CQ "$SAVE"
  1858.         setsave XVID_OPTS $HIGH_XVID_OPTS "$SAVE"
  1859.         setsave MP3_ABITRATE $HIGH_MP3_ABITRATE "$SAVE"
  1860.         setsave X264_CQ $HIGH_X264_CQ "$SAVE"
  1861.         setsave X264EXT_OPTS "level_idc=31:$HIGH_X264EXT_OPTS" "$SAVE"
  1862.         setsave X264_OPTS "level_idc=31:$HIGH_X264HIGH_OPTS" "$SAVE"
  1863.         setsave AAC_AQUAL $HIGH_AAC_AQUAL "$SAVE"
  1864.         setsave OGG_AQUAL $HIGH_OGG_AQUAL "$SAVE"
  1865.     elif echo "$QLEVEL" | grep -i "med" >/dev/null 2>&1
  1866.     then
  1867.         setsave SCALE43 $MED_SCALE43 "$SAVE"
  1868.         setsave SCALE169 $MED_SCALE169 "$SAVE"
  1869.         setsave LAVC_CQ $MED_LAVC_CQ "$SAVE"
  1870.         setsave LAVC_OPTS $MED_LAVC_OPTS "$SAVE"
  1871.         setsave XVID_CQ $MED_XVID_CQ "$SAVE"
  1872.         setsave XVID_OPTS $MED_XVID_OPTS "$SAVE"
  1873.         setsave MP3_ABITRATE $MED_MP3_ABITRATE "$SAVE"
  1874.         setsave X264_CQ $MED_X264_CQ "$SAVE"
  1875.         setsave X264EXT_OPTS "level_idc=31:$MED_X264EXT_OPTS" "$SAVE"
  1876.         setsave X264_OPTS "level_idc=31:$MED_X264HIGH_OPTS" "$SAVE"
  1877.         setsave AAC_AQUAL $MED_AAC_AQUAL "$SAVE"
  1878.         setsave OGG_AQUAL $MED_OGG_AQUAL "$SAVE"
  1879.     elif echo "$QLEVEL" | grep -i "low" >/dev/null 2>&1
  1880.     then
  1881.         setsave SCALE43 $LOW_SCALE43 "$SAVE"
  1882.         setsave SCALE169 $LOW_SCALE169 "$SAVE"
  1883.         setsave LAVC_CQ $LOW_LAVC_CQ "$SAVE"
  1884.         setsave LAVC_OPTS $LOW_LAVC_OPTS "$SAVE"
  1885.         setsave XVID_CQ $LOW_XVID_CQ "$SAVE"
  1886.         setsave XVID_OPTS $LOW_XVID_OPTS "$SAVE"
  1887.         setsave MP3_ABITRATE $LOW_MP3_ABITRATE "$SAVE"
  1888.         setsave X264_CQ $LOW_X264_CQ "$SAVE"
  1889.         setsave X264EXT_OPTS "level_idc=30:$LOW_X264EXT_OPTS" "$SAVE"
  1890.         setsave X264_OPTS "level_idc=30:$LOW_X264HIGH_OPTS" "$SAVE"
  1891.         setsave AAC_AQUAL $LOW_AAC_AQUAL "$SAVE"
  1892.         setsave OGG_AQUAL $LOW_OGG_AQUAL "$SAVE"
  1893.     elif echo "$QLEVEL" | egrep -i "480" >/dev/null 2>&1
  1894.     then
  1895.         # 480 scale, high everything else
  1896.         setsave SCALE43 $FE_SCALE43 "$SAVE"
  1897.         setsave SCALE169 $FE_SCALE169 "$SAVE"
  1898.         setsave LAVC_CQ $HIGH_LAVC_CQ "$SAVE"
  1899.         setsave LAVC_OPTS $HIGH_LAVC_OPTS "$SAVE"
  1900.         setsave XVID_CQ $HIGH_XVID_CQ "$SAVE"
  1901.         setsave XVID_OPTS $HIGH_XVID_OPTS "$SAVE"
  1902.         setsave MP3_ABITRATE $HIGH_MP3_ABITRATE "$SAVE"
  1903.         setsave X264_CQ $HIGH_X264_CQ "$SAVE"
  1904.         setsave X264EXT_OPTS "level_idc=31:$HIGH_X264EXT_OPTS" "$SAVE"
  1905.         setsave X264_OPTS "level_idc=31:$HIGH_X264HIGH_OPTS" "$SAVE"
  1906.         setsave AAC_AQUAL $HIGH_AAC_AQUAL "$SAVE"
  1907.         setsave OGG_AQUAL $HIGH_OGG_AQUAL "$SAVE"
  1908.     elif echo "$QLEVEL" | egrep -i "576" >/dev/null 2>&1
  1909.     then
  1910.         # 576 scale, high everything else
  1911.         setsave SCALE43 $FS_SCALE43 "$SAVE"
  1912.         setsave SCALE169 $FS_SCALE169 "$SAVE"
  1913.         setsave LAVC_CQ $HIGH_LAVC_CQ "$SAVE"
  1914.         setsave LAVC_OPTS $HIGH_LAVC_OPTS "$SAVE"
  1915.         setsave XVID_CQ $HIGH_XVID_CQ "$SAVE"
  1916.         setsave XVID_OPTS $HIGH_XVID_OPTS "$SAVE"
  1917.         setsave MP3_ABITRATE $HIGH_MP3_ABITRATE "$SAVE"
  1918.         setsave X264_CQ $HIGH_X264_CQ "$SAVE"
  1919.         setsave X264EXT_OPTS "level_idc=31:$HIGH_X264EXT_OPTS" "$SAVE"
  1920.         setsave X264_OPTS "level_idc=31:$HIGH_X264HIGH_OPTS" "$SAVE"
  1921.         setsave AAC_AQUAL $HIGH_AAC_AQUAL "$SAVE"
  1922.         setsave OGG_AQUAL $HIGH_OGG_AQUAL "$SAVE"
  1923.     elif echo "$QLEVEL" | egrep -i "720" >/dev/null 2>&1
  1924.     then
  1925.         # 720 scale, high everything else
  1926.         setsave SCALE43 $ST_SCALE43 "$SAVE"
  1927.         setsave SCALE169 $ST_SCALE169 "$SAVE"
  1928.         setsave LAVC_CQ $HIGH_LAVC_CQ "$SAVE"
  1929.         setsave LAVC_OPTS $HIGH_LAVC_OPTS "$SAVE"
  1930.         setsave XVID_CQ $HIGH_XVID_CQ "$SAVE"
  1931.         setsave XVID_OPTS $HIGH_XVID_OPTS "$SAVE"
  1932.         setsave MP3_ABITRATE $HIGH_MP3_ABITRATE "$SAVE"
  1933.         setsave X264_CQ $HIGH_X264_CQ "$SAVE"
  1934.         setsave X264EXT_OPTS "level_idc=41:$HIGH_X264EXT_OPTS" "$SAVE"
  1935.         setsave X264_OPTS "level_idc=41:$HIGH_X264HIGH_OPTS" "$SAVE"
  1936.         setsave AAC_AQUAL $HIGH_AAC_AQUAL "$SAVE"
  1937.         setsave OGG_AQUAL $HIGH_OGG_AQUAL "$SAVE"
  1938.     elif echo "$QLEVEL" | grep -i "1080" >/dev/null 2>&1
  1939.     then
  1940.         # 1080 scale, high everything else
  1941.         setsave SCALE43 $TE_SCALE43 "$SAVE"
  1942.         setsave SCALE169 $TE_SCALE169 "$SAVE"
  1943.         setsave LAVC_CQ $HIGH_LAVC_CQ "$SAVE"
  1944.         setsave LAVC_OPTS $HIGH_LAVC_OPTS "$SAVE"
  1945.         setsave XVID_CQ $HIGH_XVID_CQ "$SAVE"
  1946.         setsave XVID_OPTS $HIGH_XVID_OPTS "$SAVE"
  1947.         setsave MP3_ABITRATE $HIGH_MP3_ABITRATE "$SAVE"
  1948.         setsave X264_CQ $HIGH_X264_CQ "$SAVE"
  1949.         setsave X264EXT_OPTS "level_idc=42:$HIGH_X264EXT_OPTS" "$SAVE"
  1950.         setsave X264_OPTS "level_idc=42:$HIGH_X264HIGH_OPTS" "$SAVE"
  1951.         setsave AAC_AQUAL $HIGH_AAC_AQUAL "$SAVE"
  1952.         setsave OGG_AQUAL $HIGH_OGG_AQUAL "$SAVE"
  1953.     fi
  1954.     scriptlog INFO "Changed to $QLEVEL quality."
  1955. }
  1956.  
  1957. setaudiotracks() {
  1958.     local TMP=$1
  1959.     local SAVE=$2
  1960.     if [[ $TMP =~ ^([0-9]+(:[a-z]{3})?(,|$))+$ ]]
  1961.     then
  1962.         if echo $TMP | egrep -q "[1-9]" && ! is24ormore
  1963.         then
  1964.             scriptlog ERROR "Audio track selection is only supported on MythTV >= 0.24"
  1965.             TMP=$(echo $TMP | sed "s/[1-9]/0/g")
  1966.         fi
  1967.         if [ $CONTYPE != "mkv" -a $CONTYPE != "mp4" ]
  1968.         then
  1969.             if echo $TMP | grep -q ","
  1970.             then
  1971.                 scriptlog ERROR "Multiple audio tracks are only supported in mkv and mp4"
  1972.                 setsave ATRACKS "${TMP/,*/}" "$SAVE"
  1973.             fi
  1974.         else
  1975.             setsave ATRACKS "$TMP" "$SAVE"
  1976.         fi
  1977.     else
  1978.         scriptlog ERROR "Cannot parse audio tracks info"
  1979.         setsave ATRACKS 0 "$SAVE"
  1980.     fi
  1981.     scriptlog DEBUG "Audio track definitions: $ATRACKS"
  1982. }
  1983.  
  1984. parsetitle() {
  1985.     local DATA=$@
  1986.     while [[ ${DATA} =~ ([a-z]+)\|([^|]*)($| ) ]]; do
  1987.         M=${BASH_REMATCH[0]}
  1988.         [ -n "${DATA%%$M*}" ] && setsave SUBTITLE "${DATA%% $M*}" "true"
  1989.         DATA=${DATA#*$M}
  1990.         T=${BASH_REMATCH[1]}
  1991.         D=${BASH_REMATCH[2]}
  1992.         case $T in
  1993.             [tT]) setsave TITLE "$D" "true" ;;
  1994.             [sS]) setsave SUBTITLE "$D" "true" ;;
  1995.             [nN]) setsave META_SEASON "$D" "true" ;;
  1996.             [eE]) setsave META_EPISODE "$D" "true" ;;
  1997.             [aA]) setsave META_ARTIST "$D" "true" ;;
  1998.             [rR]) setsave META_DIRECTOR "$D" "true" ;;
  1999.             [bB]) setsave META_ALBUM "$D" "true" ;;
  2000.             [cC]) setsave META_COMMENT "$D" "true" ;;
  2001.             [lL]) setsave META_LOCATION "$D" "true" ;;
  2002.             [yYdD]) if [[ $D =~ ^[0-9]{4}$ ]]; then
  2003.                 date=$D
  2004.                   elif [[ $D =~ ^([0-9]{4})[^0-9]([0-9]{2})[^0-9]([0-9]{2})$ ]]; then
  2005.                 date=${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.${BASH_REMATCH[3]}
  2006.                   elif [[ $D =~ ^([0-9]{2})[^0-9]([0-9]{2})[^0-9]([0-9]{4})$ ]]; then
  2007.                 date=${BASH_REMATCH[3]}.${BASH_REMATCH[2]}.${BASH_REMATCH[1]}
  2008.                   else
  2009.                 scriptlog ERROR "Wrong date: $D"
  2010.                 continue
  2011.                   fi
  2012.                   setsave META_DATE "$date" "true"
  2013.                   ;;
  2014.             [qQ]) setquality "$D" "true" ;;
  2015.             [fF]) setcontype "$D" "true" ;;
  2016.             "aud") setaudiotracks "$D" "true" ;;
  2017.             "asp") setaspect "$D" "true" ;;
  2018.             "den") setdenoise "$D" "true" ;;
  2019.             "deb") setdeblock "$D" "true" ;;
  2020.             "dei") setdeinterlace "$D" "true" ;;
  2021.             "inv") setinvtelecine "$D" "true" ;;   
  2022.             "crop") setcrop "$D" "true" ;;
  2023.             "del") setdeleterec "$D" "true" ;;
  2024.             "chap") setchapterduration "$D" "true" ;;
  2025.             "chapf") setchapterfile "$D" "true" ;;
  2026.             "dir") [ "${D:0:1}" == "/" ] && setcopydir "$D" "true" || setcopydir "$COPYDIR/$D" "true" ;;
  2027.             "pass") setpass "$D" "true" ;;
  2028.             *) scriptlog ERROR "Unknown tag: $T|$D" ;;
  2029.         esac
  2030.     done
  2031. }
  2032.  
  2033. stoptime() {
  2034. local STARTSECS=$1
  2035. local MAXRUNHOURS=$2
  2036. local CURSECS
  2037. local ENDSECS
  2038.     [ "$MAXRUNHOURS" = "NA" ] && return 1
  2039.     CURSECS=$(date +%s)
  2040.     ENDSECS=$(( $STARTSECS + ( $MAXRUNHOURS * 60 * 60 ) ))
  2041.     [ "$ENDSECS" -gt "$CURSECS" ] && return 1 || return 0
  2042. }
  2043.  
  2044. checkoutput() {
  2045. local INPUT="$1"
  2046. local OUTPUT="$2"
  2047. local MENCODERRES="$3"
  2048. local OUTPUTCHECKS="$4"
  2049. local VIDFOR
  2050. local OUTSIZE
  2051. local INSIZE
  2052. local RAT
  2053. local SCANOUTFILE
  2054. local LCOUNT
  2055. local ECOUNT
  2056. local INFRAMES
  2057. local OUTFRAMES
  2058. local DIFF
  2059.     if echo "$OUTPUTCHECKS" | grep -v "NOSIZE" >/dev/null 2>&1
  2060.     then
  2061.         scriptlog INFO "Checking output size."
  2062.         OUTSIZE=$(stat -c %s "$OUTPUT" 2>/dev/null || echo 0)
  2063.         if [ "$OUTSIZE" -eq 0 ]
  2064.         then
  2065.             scriptlog ERROR "$OUTPUT zero length."
  2066.             scriptlog INFO "This check can be disabled with --outputchecks=NOSIZE"
  2067.             return 1
  2068.         fi
  2069.     fi
  2070.  
  2071.     if echo "$OUTPUTCHECKS" | grep -v "NOVIDINFO" >/dev/null 2>&1
  2072.     then
  2073.         scriptlog INFO "Checking output video info."
  2074.         VIDFOR=$(getvidinfo "$OUTPUT" video_format)
  2075.         case $VIDFOR in
  2076.             MPEG4|AVC|XVID|DIVX|H264)
  2077.                 true
  2078.             ;;
  2079.             *)
  2080.                 scriptlog ERROR "$OUTPUT ($VIDFOR) does not look like correct avi/mp4/mkv file."
  2081.                 scriptlog INFO "This check can be disabled with --outputchecks=NOVIDINFO"
  2082.                 return 1
  2083.             ;;
  2084.         esac
  2085.     fi
  2086.  
  2087.     if ! hascutlist $CHANID $STARTTIME && echo "$OUTPUTCHECKS" | grep -v "NOSIZERATIO" >/dev/null 2>&1
  2088.     then
  2089.         scriptlog INFO "Checking input/output size ratio."
  2090.         INSIZE=$(stat -c %s "$INPUT" 2>/dev/null || echo 0)
  2091.         RAT=$(( $INSIZE / $OUTSIZE ))
  2092.         if [ "$RAT" -gt 16 ]
  2093.         then
  2094.             scriptlog ERROR "ratio of $RAT between $INPUT and $OUTPUT sizes greater than 16."
  2095.             scriptlog INFO "This check can be disabled with --outputchecks=NOSIZERATIO"
  2096.             return 1
  2097.         fi
  2098.     fi
  2099.  
  2100.     if echo "$OUTPUTCHECKS" | grep -v "NOFRAMECOUNT" >/dev/null 2>&1 && [ -f "$MENCODERRES" ]
  2101.     then
  2102.         scriptlog INFO "Checking input/output frame count."
  2103.         INFRAMES=$(tail -40 "$MENCODERRES" | awk '/Video stream:/ {F=$12} END {print F}')
  2104.         OUTFRAMES=$(nice mencoder -nosound -ovc frameno -vc null -o /dev/null "$OUTPUT" | awk '/Video stream:/ {F=$12} END {print F}')
  2105.         scriptlog INFO "Input frames $INFRAMES $INPUT."
  2106.         scriptlog INFO "Output frames $OUTFRAMES $OUTPUT."
  2107.         if echo ${INFRAMES} : ${OUTFRAMES} | grep '[0-9] : [0-9]' >/dev/null 2>&1
  2108.         then
  2109.             DIFF=$([ $INFRAMES -gt $OUTFRAMES ] && echo $(( $INFRAMES - $OUTFRAMES )) || echo $(( $OUTFRAMES - $INFRAMES )))
  2110.         else
  2111.             scriptlog ERROR "Could not get frame count."
  2112.             scriptlog INFO "This check can be disabled with --outputchecks=NOFRAMECOUNT"
  2113.             return 1
  2114.         fi
  2115.         if [ "$DIFF" -gt 10 ]
  2116.         then
  2117.             scriptlog ERROR "Frame count difference of $DIFF between $INPUT and $OUTPUT greater than 10."
  2118.             scriptlog INFO "This check can be disabled with --outputchecks=NOFRAMECOUNT"
  2119.             return 1
  2120.         fi
  2121.     fi
  2122.  
  2123.     if echo "$OUTPUTCHECKS" | grep -v "NOSCAN" >/dev/null 2>&1
  2124.     then
  2125.         scriptlog INFO "Scanning output for errors. (Takes a long time)"
  2126.         SCANOUTFILE="${FIFODIR}/mplayerscan-out"
  2127.         nice mplayer -nojoystick -nolirc -nomouseinput -vo null -ao null -speed 10 "$OUTPUT" 2>&1 | tr '\r' '\n' >$SCANOUTFILE 2>&1
  2128.         LCOUNT=$(wc -l $SCANOUTFILE 2>/dev/null | awk '{T=$1} END {if(T>0){print T}else{print 0}}')
  2129.         if [ "$LCOUNT" -lt 1000 ]
  2130.         then
  2131.             scriptlog ERROR "mplayer line count of $LCOUNT to low on $OUTPUT."
  2132.             scriptlog INFO "This check can be disabled with --outputchecks=NOSCAN"
  2133.             return 1
  2134.         fi
  2135.         ECOUNT=$(egrep -ic 'sync|error|skip|damaged|overflow' $SCANOUTFILE)
  2136.         if [ "$ECOUNT" -gt "$MPLAYER_ERROR_COUNT" ]
  2137.         then
  2138.             scriptlog ERROR "mplayer error count too great ($ECOUNT > $MPLAYER_ERROR_COUNT) on $OUTPUT."
  2139.             scriptlog INFO "You can change the error limit variable MPLAYER_ERROR_COUNT at top of script or"
  2140.             scriptlog INFO "The check can be disabled with --outputchecks=NOSCAN"
  2141.             return 1
  2142.         fi
  2143.     fi
  2144.  
  2145.     return 0
  2146. }
  2147.  
  2148. getcategory() {
  2149. local CHANID="$1"
  2150. local STARTTIME="$2"
  2151. local DATA
  2152.     [ -n "$CHANID" ] || return 1
  2153.     DATA=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  2154.     select category from recorded where chanid = $CHANID and starttime = "$STARTTIME";
  2155.     EOF
  2156.     )
  2157.     echo $DATA | tr -d '[:cntrl:]' | tr -d '[:punct:]'
  2158. }
  2159.  
  2160. getplot() {
  2161. local CHANID="$1"
  2162. local STARTTIME="$2"
  2163. local DATA
  2164.     [ -n "$CHANID" ] || return 1
  2165.     DATA=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  2166.     select description from recorded where chanid = $CHANID and starttime = "$STARTTIME";
  2167.     EOF
  2168.     )
  2169.     echo $DATA | tr -d '[:cntrl:]' | tr -d '[:punct:]'
  2170. }
  2171.  
  2172. getyear() {
  2173. local CHANID="$1"
  2174. local STARTTIME="$2"
  2175. local DATA
  2176.     [ -n "$CHANID" ] || return 1
  2177.     # STARTTIME is not always the same in both tables for matching programs. ???
  2178.     DATA=$(mysql --batch --skip-column-names --user="${DBUserName}" --password="${DBPassword}" -h "${DBHostName}" "${DBName}" <<-EOF
  2179.     select airdate from recorded a,recordedprogram b
  2180.     where a.chanid = $CHANID and a.starttime = "$STARTTIME" and a.chanid = b.chanid
  2181.     and a.title = b.title and a.subtitle = b.subtitle;
  2182.     EOF
  2183.     )
  2184.     [ -n "$DATA" -a $DATA -gt 1800 ] && echo $DATA || echo $(date +%Y)
  2185. }
  2186.  
  2187.  
  2188. genchapfile() {
  2189. local FILE="$1"
  2190. local DURATION=$(( $2 * 60 ))
  2191. local CONTYPE="$3"
  2192. local CHAPTERFILE="${FIFODIR}/chapters.txt"
  2193. local LENGTH
  2194. local CHAPTER
  2195. local COUNT
  2196. local CHAPMINS
  2197. local CHAPHOURS
  2198. local CHAPSECS
  2199.     {
  2200.     if [ "$CONTYPE" != "mkv" -a "$CONTYPE" != "mp4" ]
  2201.     then
  2202.         scriptlog ERROR "Container type does not support chapters."
  2203.         return 1
  2204.     fi
  2205.     LENGTH=$(getlength "$FILE") # Must use midentify
  2206.     LENGTH=$(echo $LENGTH | cut -d'.' -f1)
  2207.     if [ -z "$LENGTH"  -o "$LENGTH" -lt 1 ]
  2208.     then
  2209.         scriptlog ERROR "Invalid Length $LENGTH seconds"
  2210.         return 1
  2211.     else
  2212.         scriptlog INFO "Length $LENGTH seconds, chapter every $DURATION seconds. $(( ( $LENGTH / $DURATION ) + 1 )) Chapters"
  2213.     fi
  2214.     CHAPTER=0 ; COUNT=1
  2215.     touch "$CHAPTERFILE"
  2216.     while [ "$CHAPTER" -lt "$LENGTH" ]
  2217.     do
  2218.         scriptlog DEBUG "CHAPTERFILE $CHAPTERFILE CHAPTER $CHAPTER LENGTH $LENGTH"
  2219.         CHAPMINS=$(( $CHAPTER / 60 ))
  2220.         CHAPHOURS=$(( $CHAPMINS / 60 ))
  2221.         CHAPMINS=$(( $CHAPMINS - ( $CHAPHOURS * 60 ) ))
  2222.         CHAPSECS=$(( $CHAPTER - ( ( $CHAPHOURS * 60 * 60 ) + ( $CHAPMINS * 60 ) ) ))
  2223.         printf 'CHAPTER%s=%02d:%02d:%02d.000\n' ${COUNT} ${CHAPHOURS} ${CHAPMINS} ${CHAPSECS} >> "$CHAPTERFILE"
  2224.         echo "CHAPTER${COUNT}NAME=Chapter $COUNT" >> "$CHAPTERFILE"
  2225.         COUNT=$(( $COUNT + 1 ))
  2226.         CHAPTER=$(( $CHAPTER + $DURATION ))
  2227.     done
  2228.     } >/dev/null 2>&1
  2229.     echo "$CHAPTERFILE"
  2230. }
  2231.  
  2232. encloseincontainer() {
  2233. local OUTBASE="$1"
  2234. local FPS="$2"
  2235. local AUDEXT="$3"
  2236. local CONTYPE="$4"
  2237. local ASPECT="$5"
  2238. local ATRACKS="$6"
  2239. local TITLE="$7"
  2240. local CHAPTERFILE="$8"
  2241. local CHAPTERS=""
  2242. local RET
  2243. local MKVTRACKS
  2244. local MP4TRACKS
  2245. local MKVTITLE
  2246. local TRACK
  2247. local FILE
  2248.     for ATRACK in ${ATRACKS//,/ }
  2249.     do
  2250.         TRACK=${ATRACK:0:1}
  2251.         LANG=${ATRACK:2:3}
  2252.         FILE=${OUTBASE}_audio${TRACK}.${AUDEXT}
  2253.  
  2254.         if [ ! -f "$FILE" ]
  2255.         then
  2256.             scriptlog ERROR "$FILE does not exist."
  2257.             return 1
  2258.         fi
  2259.  
  2260.         [ -n "$LANG" ] && MKVTRACKS="$MKVTRACKS --language 0:$LANG"
  2261.         MKVTRACKS="$MKVTRACKS $FILE"
  2262.  
  2263.         MP4TRACKS="$MP4TRACKS -add $FILE"
  2264.         [ -n "$LANG" ] && MP4TRACKS="${MP4TRACKS}:lang=$LANG"
  2265.     done
  2266.     if [ -f "${OUTBASE}_video.h264" ]
  2267.     then
  2268.         if [ "$CONTYPE" = "mkv" ]
  2269.         then
  2270.             [ -f "$CHAPTERFILE" ] && CHAPTERS="--chapters $CHAPTERFILE"
  2271.                     MKVTITLE="$TITLE"
  2272.                     [ -n "$SUBTITLE" ] && COPYFILE="$MKVTITLE - $SUBTITLE"
  2273.                     [ -n "$META_ARTIST" ] && MKVTITLE="$META_ARTIST - $MKVTITLE"
  2274.  
  2275.             cat > ${OUTBASE}_tags.xml <<-EOF
  2276.             <?xml version="1.0" encoding="UTF-8"?>
  2277.             <!DOCTYPE Tags SYSTEM "matroskatags.dtd">
  2278.             <Tags>
  2279.               <Tag>
  2280.                 <Targets>
  2281.             EOF
  2282.  
  2283.             # music video
  2284.             if [ -n "$META_ALBUM" ]
  2285.             then
  2286.                 cat >> ${OUTBASE}_tags.xml <<-EOF
  2287.                       <TargetTypeValue>50</TargetTypeValue>
  2288.                     </Targets>
  2289.                     <Simple>
  2290.                       <Name>TITLE</Name>
  2291.                       <String>$META_ALBUM</String>
  2292.                     </Simple>
  2293.                   </Tag>
  2294.                   <Tag>
  2295.                     <Targets>
  2296.                       <TargetTypeValue>30</TargetTypeValue>
  2297.                     </Targets>
  2298.                     <Simple>
  2299.                       <Name>TITLE</Name>
  2300.                       <String>$TITLE</String>
  2301.                     </Simple>
  2302.                 EOF
  2303.  
  2304.             # series episode
  2305.             elif [ -n "$META_EPISODE" ]
  2306.             then
  2307.                 cat >> ${OUTBASE}_tags.xml <<-EOF
  2308.                       <TargetTypeValue>70</TargetTypeValue>
  2309.                     </Targets>
  2310.                     <Simple>
  2311.                       <Name>TITLE</Name>
  2312.                       <String>$TITLE</String>
  2313.                     </Simple>
  2314.                   </Tag>
  2315.                 EOF
  2316.                 if [ -n "$META_SEASON" ]
  2317.                 then
  2318.                     cat >> ${OUTBASE}_tags.xml <<-EOF
  2319.                       <Tag>
  2320.                         <Targets>
  2321.                           <TargetTypeValue>50</TargetTypeValue>
  2322.                         </Targets>
  2323.                         <Simple>
  2324.                           <Name>PART_NUMBER</Name>
  2325.                           <String>$META_SEASON</String>
  2326.                         </Simple>
  2327.                       </Tag>
  2328.                     EOF
  2329.                 fi
  2330.                 cat >> ${OUTBASE}_tags.xml <<-EOF
  2331.                   <Tag>
  2332.                     <Targets>
  2333.                       <TargetTypeValue>30</TargetTypeValue>
  2334.                     </Targets>
  2335.                     <Simple>
  2336.                       <Name>PART_NUMBER</Name>
  2337.                       <String>$META_EPISODE</String>
  2338.                     </Simple>
  2339.                     <Simple>
  2340.                       <Name>TITLE</Name>
  2341.                       <String>$SUBTITLE</String>
  2342.                     </Simple>
  2343.                 EOF
  2344.  
  2345.             # general
  2346.             else
  2347.                 cat >> ${OUTBASE}_tags.xml <<-EOF
  2348.                       <TargetTypeValue>50</TargetTypeValue>
  2349.                     </Targets>
  2350.                     <Simple>
  2351.                       <Name>TITLE</Name>
  2352.                       <String>$TITLE</String>
  2353.                     </Simple>
  2354.                 EOF
  2355.                
  2356.                     [ -n "$SUBTITLE" ] && cat >> ${OUTBASE}_tags.xml <<-EOF
  2357.                     <Simple>
  2358.                       <Name>SUBTITLE</Name>
  2359.                       <String>$SUBTITLE</String>
  2360.                     </Simple>
  2361.                 EOF
  2362.             fi
  2363.  
  2364.             [ -n "$META_ARTIST" ] && cat >> ${OUTBASE}_tags.xml <<-EOF
  2365.                 <Simple>
  2366.                   <Name>ARTIST</Name>
  2367.                   <String>$META_ARTIST</String>
  2368.                 </Simple>
  2369.             EOF
  2370.  
  2371.             [ -n "$META_DIRECTOR" ] && cat >> ${OUTBASE}_tags.xml <<-EOF
  2372.                 <Simple>
  2373.                   <Name>DIRECTOR</Name>
  2374.                   <String>$META_DIRECTOR</String>
  2375.                 </Simple>
  2376.             EOF
  2377.  
  2378.             [ -n "$META_DATE" ] && cat >> ${OUTBASE}_tags.xml <<-EOF
  2379.                 <Simple>
  2380.                   <Name>DATE_RELEASED</Name>
  2381.                   <String>$META_DATE</String>
  2382.                 </Simple>
  2383.             EOF
  2384.  
  2385.             [ -n "$META_COMMENT" ] && cat >> ${OUTBASE}_tags.xml <<-EOF
  2386.                 <Simple>
  2387.                   <Name>COMMENT</Name>
  2388.                   <String>$META_COMMENT</String>
  2389.                 </Simple>
  2390.             EOF
  2391.  
  2392.             [ -n "$META_LOCATION" ] && cat >> ${OUTBASE}_tags.xml <<-EOF
  2393.                 <Simple>
  2394.                   <Name>RECORDING_LOCATION</Name>
  2395.                   <String>$META_LOCATION</String>
  2396.                 </Simple>
  2397.             EOF
  2398.  
  2399.             cat >> ${OUTBASE}_tags.xml <<-EOF
  2400.               </Tag>
  2401.             </Tags>
  2402.             EOF
  2403.  
  2404.             if [ "$MKVMERGE251BUG" = "YES" ]
  2405.             then
  2406.                 scriptlog DEBUG Muxing: LANG=C mkvmerge --global-tags "${OUTBASE}_tags.xml" --default-duration 0:${FPS}fps --aspect-ratio 0:${ASPECT} --title "$MKVTITLE" $CHAPTERS \
  2407.                 "${OUTBASE}_video.h264" $MKVTRACKS -o "${OUTBASE}.mkv"
  2408.                 LANG=C mkvmerge --global-tags "${OUTBASE}_tags.xml" --default-duration 0:${FPS}fps --aspect-ratio 0:${ASPECT} --title "$MKVTITLE" $CHAPTERS \
  2409.                 "${OUTBASE}_video.h264" $MKVTRACKS -o "${OUTBASE}.mkv"
  2410.                 RET=$? ; [ $RET -eq 1 ] && RET=0 # mkvmerge return code of 1 is only a warning
  2411.             else
  2412.                 scriptlog DEBUG Muxing: mkvmerge --global-tags "${OUTBASE}_tags.xml" --default-duration 0:${FPS}fps --aspect-ratio 0:${ASPECT} --title "$MKVTITLE" $CHAPTERS \
  2413.                 "${OUTBASE}_video.h264" $MKVTRACKS -o "${OUTBASE}.mkv"
  2414.                 mkvmerge --global-tags "${OUTBASE}_tags.xml" --default-duration 0:${FPS}fps --aspect-ratio 0:${ASPECT} --title "$MKVTITLE" $CHAPTERS \
  2415.                 "${OUTBASE}_video.h264" $MKVTRACKS -o "${OUTBASE}.mkv"
  2416.                 RET=$? ; [ $RET -eq 1 ] && RET=0 # mkvmerge return code of 1 is only a warning
  2417.             fi
  2418.         elif [ "$CONTYPE" = "mp4" ]
  2419.         then
  2420.             [ -f "$CHAPTERFILE" ] && CHAPTERS="-chap $CHAPTERFILE"
  2421.             MP4Box -add "${OUTBASE}_video.h264:par=1:1" $MP4TRACKS -fps $FPS $CHAPTERS "${OUTBASE}.mp4"
  2422.             RET=$?
  2423.         fi
  2424.         if [ $RET -eq 0 ]
  2425.         then
  2426.             [ "$DEBUG" != "ON" ] && rm -f "${OUTBASE}_video.h264" "${OUTBASE}_audio*.${AUDEXT}" "${OUTBASE}_tags.xml"
  2427.         else
  2428.             [ "$DEBUG" != "ON" ] && rm -f "${OUTBASE}_video.h264" "${OUTBASE}_audio*.${AUDEXT}" "${OUTBASE}_tags.xml" "${OUTBASE}.mkv" >/dev/null 2>&1
  2429.             return 1
  2430.         fi
  2431.     else
  2432.         scriptlog ERROR "${OUTBASE}_video.h264 does not exist."
  2433.         return 1
  2434.     fi
  2435.     return 0
  2436. }
  2437.  
  2438. logtranstime () {
  2439. local START=$1
  2440. local END=$2
  2441. local ORIGINALFILESIZE=$3
  2442. local NEWFILESIZE=$4
  2443.     TMP=$(( $(date -u -d"${END}" +%s) - $(date -u -d"${START}" +%s) ))
  2444.     DAYS=$(( $TMP / 60 / 60 / 24 ))
  2445.     HOURS=$(( $TMP / 60 / 60 - ($DAYS * 24) ))
  2446.     MINUTES=$(( $TMP / 60 - ( ($HOURS * 60)+($DAYS * 24 * 60) ) ))
  2447.     SECONDS=$(( $TMP - ( ($MINUTES * 60)+($HOURS * 60 * 60)+($DAYS * 24 * 60 * 60) ) ))
  2448.     scriptlog INFO "RUNTIME: $DAYS days $HOURS hours $MINUTES minutes and $SECONDS seconds. Original filesize: $ORIGINALFILESIZE New filesize: $NEWFILESIZE"
  2449. }
  2450.  
  2451. boinccontrol() {
  2452. local BOINCCOMMAND="$1"
  2453. # BOINCPASSWD global
  2454.     [ -n "$BOINCPASSWD" ] || return 1
  2455.     for p in $(boinccmd --host "localhost" --passwd "$BOINCPASSWD" --get_project_status | awk '/master URL:/ {print $3}')
  2456.     do
  2457.         if boinccmd --host "localhost" --passwd "$BOINCPASSWD" --project "$p" "$BOINCCOMMAND" >/dev/null 2>&1
  2458.         then
  2459.             scriptlog INFO "Boinc project $p $BOINCCOMMAND."
  2460.         else
  2461.             scriptlog INFO "Boinc project $p FAILED to $BOINCCOMMAND."
  2462.         fi
  2463.     done
  2464. }
  2465.  
  2466. cleanup() {
  2467. local SIG="$1"
  2468. local JOBID="$2"
  2469. local OUTPUT="$3"
  2470. local OUTBASE
  2471. local TRANPID
  2472.     scriptlog DEBUG "$SIG Clean up."
  2473.     if [ "$SIG" = "ABRT" ]
  2474.     then
  2475.         scriptlog ERROR "Job Aborted. Removing incomplete $OUTPUT."
  2476.         OUTBASE=$(echo "$OUTPUT" | sed -e 's/\.[ma][pv][4i]$//')
  2477.         [ "$DEBUG" != "ON" ] && rm -f "${OUTBASE}.avi" "${OUTBASE}_video.h264" "${OUTBASE}_audio*.aac" "${OUTBASE}_audio*.ogg" "${OUTBASE}_tags.xml" "${OUTBASE}.mp4" "${OUTBASE}.mkv" >/dev/null 2>&1
  2478.     fi
  2479.  
  2480.     TRANPID=$(jobs -l | awk '/mythtranscode/ {P=$2" "P} END {print P}')
  2481.     if [ -n "$TRANPID" ]
  2482.     then
  2483.         scriptlog DEBUG "Killing mythtranscode [$TRANPID]"
  2484.         ps -p $TRANPID >/dev/null 2>&1 && kill $TRANPID >/dev/null 2>&1
  2485.     fi
  2486.  
  2487.     # resume boinc
  2488.     boinccontrol "resume"
  2489.  
  2490.     if [ "$FINALEXIT" -eq 0 ]
  2491.     then
  2492.         [ "$DEBUG" != "ON" ] && rm -rf "$FIFODIR" >/dev/null 2>&1
  2493.         scriptlog INFO "Exiting. Successful."
  2494.         if [ "$JOBID" -ne 99999999 ]
  2495.         then
  2496.             setjobqueuestatus "$JOBID" "FINISHED"
  2497.             setjobqueuecomment "$JOBID" "[${$}] Successfully Completed"
  2498.         fi
  2499.         exit 0
  2500.     else
  2501.         scriptlog INFO "Exiting. Errored."
  2502.         if [ "$JOBID" -ne 99999999 ]
  2503.         then
  2504.             setjobqueuestatus "$JOBID" "ERRORED"
  2505.             setjobqueuecomment "$JOBID" "[${$}] Errored"
  2506.         fi
  2507.         # Only error code jobqueue.cpp interprets is 246. This is translated to "unable to find executable".
  2508.         #scriptlog ERROR "This error could be for many reasons. Mythtv will report unable to find executable, this is incorrect."
  2509.         is21orless && exit 246 || exit 1
  2510.     fi
  2511. }
  2512.  
  2513.  
  2514. MYSQLLIST="$MYSQLTXT /home/mythtv/.mythtv/mysql.txt ${HOME}/.mythtv/mysql.txt /.mythtv/mysql.txt /usr/local/share/mythtv/mysql.txt /usr/share/mythtv/mysql.txt /etc/mythtv/mysql.txt /usr/local/etc/mythtv/mysql.txt mysql.txt"
  2515. for m in $MYSQLLIST
  2516. do
  2517.     [ -f $m ] && . $m && break
  2518. done
  2519. if [ -z "$DBName" ]
  2520. then
  2521.     echo "Can't find mysql.txt. Change MYSQLTXT variable at top of script with your mysql.txt path"
  2522.     exit 1
  2523. fi
  2524.  
  2525. ##### BG Monitor #####################################
  2526. # This will be fired off in background to update the jobqueue comment and process stop/pause/resume requests.
  2527. if echo "$1" | egrep -i '\-\-monitor=' >/dev/null 2>&1
  2528. then
  2529.     readonly MONJOBID=$(echo "$1" | cut -d'=' -f2)
  2530.     readonly MONPID="$2"
  2531.     readonly MONTRANSOP="$3"
  2532.     readonly LOGFILE="$4"
  2533.     readonly DBLOGGING=$(getsetting "LogEnabled")
  2534.  
  2535.     [ "$MONJOBID" -ne 99999999 -a -n "$MONPID" ] || exit 1
  2536.  
  2537.     PAUSEALREADYPRINTED="" ; RESUMEALREADYPRINTED=""
  2538.    
  2539.     scriptlog INFO "Starting monitoring process."
  2540.     sleep 5
  2541.     while ps -p $MONPID >/dev/null 2>&1
  2542.     do
  2543.         JQCMD=$(getjobqueuecmds "$MONJOBID")
  2544.         if [ "$JQCMD" = "PAUSE" ]
  2545.         then
  2546.             JQSTATUS=$(getjobqueuestatus "$MONJOBID")
  2547.             if [ "$JQSTATUS" != "PAUSED" ]
  2548.             then
  2549.                 MENCODERPID=$(ps --ppid $MONPID | awk '/mencoder/ {print $1}')
  2550.                 if [ -n "$MENCODERPID" ]
  2551.                 then
  2552.                     PAUSEALREADYPRINTED=""
  2553.                     STARTPAUSESECS=$(date +%s)
  2554.                     kill -s STOP $MENCODERPID
  2555.                     setjobqueuestatus "$MONJOBID" "PAUSED"
  2556.                     SAVEDCC=$(getjobqueuecomment "$MONJOBID")
  2557.                     setjobqueuecomment "$MONJOBID" "[$MONPID] Paused for 0 Seconds"
  2558.                     scriptlog STOP "Job Paused due to job queue pause request."
  2559.                 else
  2560.                     [ -z "$PAUSEALREADYPRINTED" ] && scriptlog ERROR "Sorry, could not pause. Will keep trying"
  2561.                     PAUSEALREADYPRINTED=TRUE
  2562.                 fi
  2563.             else
  2564.                 NOW=$(date +%s)
  2565.                 PAUSESECS=$(( $NOW - $STARTPAUSESECS ))
  2566.                 PAUSEMINS=$(( $PAUSESECS / 60 ))
  2567.                 PAUSEHOURS=$(( $PAUSEMINS / 60 ))
  2568.                 PAUSEMINS=$(( $PAUSEMINS - ( $PAUSEHOURS * 60 ) ))
  2569.                 PAUSESECS=$(( $PAUSESECS - ( ( $PAUSEHOURS * 60 * 60 ) + ( $PAUSEMINS * 60 ) ) ))
  2570.                 setjobqueuecomment "$MONJOBID" "[$MONPID] Paused for $PAUSEHOURS Hrs $PAUSEMINS Mins $PAUSESECS Secs"
  2571.             fi
  2572.         elif [ "$JQCMD" = "RESUME" ]
  2573.         then
  2574.             JQSTATUS=$(getjobqueuestatus "$MONJOBID")
  2575.             if [ "$JQSTATUS" != "RUNNING" ]
  2576.             then
  2577.                 MENCODERPID=$(ps --ppid $MONPID | awk '/mencoder/ {print $1}')
  2578.                 if [ -n "$MENCODERPID" ]
  2579.                 then
  2580.                     RESUMEALREADYPRINTED=""
  2581.                     kill -s CONT $MENCODERPID
  2582.                     setjobqueuestatus "$MONJOBID" "RUNNING"
  2583.                     setjobqueuecomment "$MONJOBID" "$SAVEDCC"
  2584.                     scriptlog START "Job resumed due to job queue resume request."
  2585.                     setjobqueuecmds "$MONJOBID" "RUN"
  2586.                 else
  2587.                     [ -z "$RESUMEALREADYPRINTED" ] && scriptlog ERROR "Sorry, could not resume. Will keep trying"
  2588.                     RESUMEALREADYPRINTED=TRUE
  2589.                 fi
  2590.             fi
  2591.         elif [ "$JQCMD" = "STOP" ]
  2592.         then
  2593.             setjobqueuestatus "$MONJOBID" "ABORTING"
  2594.             setjobqueuecomment "$MONJOBID" "[$MONPID] Stopping"
  2595.             scriptlog STOP "Stopping due to job queue stop request."
  2596.             setjobqueuecmds "$MONJOBID" "RUN"
  2597.             kill -s ABRT $MONPID
  2598.             sleep 2
  2599.             kill $MONPID
  2600.         elif [ "$JQCMD" = "RESTART" ]
  2601.         then
  2602.             scriptlog ERROR "Sorry, can't restart job."
  2603.             setjobqueuecmds "$MONJOBID" "RUN"
  2604.         else
  2605.             CC=$(getjobqueuecomment "$MONJOBID")
  2606.             if echo "$CC" | grep 'audio pass' >/dev/null 2>&1
  2607.             then
  2608.                 PASSNU="audio pass"
  2609.             elif echo "$CC" | grep 'Single video pass' >/dev/null 2>&1
  2610.             then
  2611.                 PASSNU="Single video pass"
  2612.             elif echo "$CC" | grep '1st video pass' >/dev/null 2>&1
  2613.             then
  2614.                 PASSNU="1st video pass"
  2615.             elif echo "$CC" | grep '2nd video pass' >/dev/null 2>&1
  2616.             then
  2617.                 PASSNU="2nd video pass"
  2618.             else
  2619.                 sleep 15
  2620.                 continue
  2621.             fi
  2622.             PCTLINE=$(tail -10 "$MONTRANSOP" | grep 'mythtranscode:' | cut -c39- | tail -1)
  2623.             [ -n "$PASSNU" -a -n "$PCTLINE" ] && setjobqueuecomment "$MONJOBID" "[$MONPID] $PASSNU $PCTLINE"
  2624.         fi
  2625.         sleep 15
  2626.     done
  2627.     exit
  2628. fi
  2629.  
  2630. ##### Globals ########################################
  2631. readonly CMD="$0"
  2632. readonly LOGFILE="${LOGBASEDIR}/mythnuv2mkv${$}.log"
  2633. readonly FIFODIR="${LOGBASEDIR}/mythnuv2mkv${$}"
  2634. readonly MENCODEROP="${FIFODIR}/mencoder.op"
  2635. readonly TRANSOP="${FIFODIR}/transcode.op"
  2636. readonly STOPREQUEST="${FIFODIR}/STOPREQUEST"
  2637. if ! tty >/dev/null 2>&1
  2638. then
  2639.     readonly BOLDON=""
  2640.     readonly ALLOFF=""
  2641.     readonly REDFG=""
  2642.     readonly GREENFG=""
  2643.     readonly COLOURORIG=""
  2644.     [ "$DEBUG" = "ON" ] && exec 3>"${LOGBASEDIR}/DEBUG" || exec 3>/dev/null
  2645.     exec 1>&3
  2646.     exec 2>&3
  2647. else
  2648.     readonly BOLDON=`tput bold`
  2649.     readonly ALLOFF=`tput sgr0`
  2650.     readonly REDFG=`tput setaf 1`
  2651.     readonly GREENFG=`tput setaf 2`
  2652.     readonly COLOURORIG=`tput op`
  2653. fi
  2654. # DBLOGGING is reverse to shell true/false
  2655. DBLOGGING=0
  2656. OUTPUT=""
  2657. JOBID=99999999
  2658. FINALEXIT=0
  2659. STARTSECS="NA"
  2660. MAXRUNHOURS="NA"
  2661. MKVMERGE251BUG="NO"
  2662.  
  2663. ##### Main ###########################################
  2664. if echo "$1" | egrep -i '\-help|\-usage|\-\?' >/dev/null 2>&1
  2665. then
  2666.     echo "$HELP"
  2667.     exit 1
  2668. fi
  2669.  
  2670. if [ "$CONTYPE" = "mkv" ]
  2671. then
  2672.     chkreqs "$MKVREQPROGS" "$MKVREQLIBS" || exit 1
  2673.     versioncheck "mkvmerge"
  2674. elif [ "$CONTYPE" = "mp4" ]
  2675. then
  2676.     chkreqs "$MP4REQPROGS" "$MP4REQLIBS" || exit 1
  2677. elif [ "$CONTYPE" = "avi" ]
  2678. then
  2679.     chkreqs "$AVIREQPROGS" "$AVIREQLIBS" || exit 1
  2680. fi
  2681. if ! versioncheck "convert"
  2682. then
  2683.     scriptlog INFO "The program \"convert\" does not appear to be the ImageMagick one. This will only affect coverfile creation."
  2684. fi
  2685.  
  2686. trap 'cleanup ABRT "$JOBID" "$OUTPUT"' INT ABRT
  2687. trap 'touch $STOPREQUEST ; scriptlog INFO "USR1 received. Will stop after current file completes."' USR1
  2688. trap 'cleanup EXIT "$JOBID"' EXIT
  2689. mkdir -m 775 -p "${LOGBASEDIR}" >/dev/null 2>&1 || scriptlog ERROR "Could not create ${LOGBASEDIR}"
  2690. mkdir -m 775 -p "${FIFODIR}" >/dev/null 2>&1 || scriptlog ERROR "Could not create ${FIFODIR}"
  2691. [ -w "${LOGBASEDIR}" ] || scriptlog ERROR "${LOGBASEDIR} not writable"
  2692. [ -w "${FIFODIR}" ] || scriptlog ERROR "${FIFODIR} not writable"
  2693. [ ${FINALEXIT} ] || exit $FINALEXIT
  2694.  
  2695. # Set default quality
  2696. [ -n "${QUALITY}" ] && setquality ${QUALITY}
  2697.  
  2698. for INPUT in "$@"
  2699. do
  2700.     if stoptime $STARTSECS $MAXRUNHOURS
  2701.     then
  2702.         scriptlog STOP "Stopping due to max runtime $MAXRUNHOURS."
  2703.         scriptlog BREAK
  2704.         break
  2705.     fi
  2706.     if [ -f "$STOPREQUEST" ]
  2707.     then
  2708.         scriptlog STOP "Stopping due to USR1 request."
  2709.         scriptlog BREAK
  2710.         break
  2711.     fi
  2712.  
  2713.     # Jobid from myth user job %JOBID%
  2714.     if echo "$INPUT" | grep -i '\-\-jobid=' >/dev/null 2>&1
  2715.     then
  2716.         JOBID=$(echo "$INPUT" | cut -d'=' -f2)
  2717.         DBLOGGING=$(getsetting "LogEnabled")
  2718.         continue
  2719.     fi
  2720.  
  2721.     if echo "$INPUT" | grep -i '\-\-findtitle=' >/dev/null 2>&1
  2722.     then
  2723.         SEARCHTITLE=$(echo "$INPUT" | cut -d'=' -f2)
  2724.         MATCHTITLE=$(findchanidstarttime "$SEARCHTITLE")   
  2725.         echo "$MATCHTITLE"
  2726.         exit 0
  2727.     fi
  2728.  
  2729.     if echo "$INPUT" | grep -i '\-\-maxrunhours=' >/dev/null 2>&1
  2730.     then
  2731.         STARTSECS=$(date +%s)
  2732.         MAXRUNHOURS=$(echo "$INPUT" | cut -d'=' -f2)
  2733.         scriptlog INFO "Max Run Hours set to $MAXRUNHOURS."
  2734.         continue
  2735.     fi
  2736.  
  2737.     if echo "$INPUT" | grep -i '\-\-debugsg' >/dev/null 2>&1
  2738.     then
  2739.         DEBUGSG="ON"
  2740.         scriptlog INFO "DEBUGSG set ON."
  2741.         continue
  2742.     fi
  2743.     if echo "$INPUT" | grep -i '\-\-debug=' >/dev/null 2>&1
  2744.     then
  2745.         DEBUG=$(echo "$INPUT" | cut -d'=' -f2 | tr '[a-z]' '[A-Z]')
  2746.         scriptlog INFO "Debug set to $DEBUG."
  2747.         continue
  2748.     fi
  2749.     if echo "$INPUT" | grep -i '\-\-info=' >/dev/null 2>&1
  2750.     then
  2751.         INFO=$(echo "$INPUT" | cut -d'=' -f2 | tr '[a-z]' '[A-Z]')
  2752.         scriptlog INFO "Info set to $INFO."
  2753.         continue
  2754.     fi
  2755.     if echo "$INPUT" | grep -i '\-\-savenuv=' >/dev/null 2>&1
  2756.     then
  2757.         SAVENUV=$(echo "$INPUT" | cut -d'=' -f2 | tr '[a-z]' '[A-Z]')
  2758.         scriptlog INFO "SaveNUV set to $SAVENUV."
  2759.         continue
  2760.     fi
  2761.  
  2762.     if echo "$INPUT" | grep -i '\-\-outputchecks=' >/dev/null 2>&1
  2763.     then
  2764.         OUTPUTCHECKS=$(echo "$INPUT" | cut -d'=' -f2 | tr '[a-z]' '[A-Z]')
  2765.         scriptlog INFO "Output checks set to $OUTPUTCHECKS."
  2766.         continue
  2767.     fi
  2768.  
  2769.     shopt -s nocasematch
  2770.     if [[ "$INPUT" =~ --(aspect|denoise|deblock|deinterlace|invtelecine|crop|deleterec|chapterduration|chapterfile|copydir|contype|pass|quality|audiotracks)\=(.*) ]]
  2771.     then
  2772.         set${BASH_REMATCH[1]} "${BASH_REMATCH[2]}"
  2773.         continue
  2774.     fi
  2775.     shopt -u nocasematch
  2776.  
  2777.     if echo "$INPUT" | grep -i '\-\-chanid=' >/dev/null 2>&1
  2778.     then
  2779.         CHANID=$(echo "$INPUT" | cut -d'=' -f2)
  2780.         continue
  2781.     fi
  2782.     if echo "$INPUT" | grep -i '\-\-starttime=' >/dev/null 2>&1
  2783.     then
  2784.         STARTTIME=$(echo "$INPUT" | cut -d'=' -f2)
  2785.         if [ -z "$CHANID" ]
  2786.         then
  2787.             scriptlog ERROR "Skipping $STARTTIME. chanid not specified."
  2788.             scriptlog ERROR "--chanid must be specified before --starttime."
  2789.             scriptlog BREAK
  2790.             unset STARTTIME
  2791.             continue
  2792.         fi
  2793.         if [ "$DEBUGSG" = "ON" ]
  2794.         then
  2795.             INPUT=$(getrecordfile "$CHANID" "$STARTTIME" "$DEBUGSG")
  2796.             scriptlog INFO "$INPUT"
  2797.             scriptlog BREAK
  2798.             exit $FINALEXIT
  2799.         fi
  2800.         INPUT=$(getrecordfile "$CHANID" "$STARTTIME")
  2801.         if [ -z "$INPUT" ]
  2802.         then
  2803.             scriptlog ERROR "Skipping $CHANID $STARTTIME. Did not match a recording."
  2804.             scriptlog BREAK
  2805.             unset CHANID STARTTIME
  2806.             continue
  2807.         fi
  2808.         if [ ! -f "$INPUT" ]
  2809.         then
  2810.             scriptlog ERROR "Could not find Recording. ($INPUT)"
  2811.             scriptlog BREAK
  2812.             unset CHANID STARTTIME
  2813.             continue
  2814.         fi
  2815.         TITLE=$(gettitle $CHANID $STARTTIME)
  2816.         SUBTITLE=$(getsubtitle $CHANID $STARTTIME)
  2817.         parsetitle $SUBTITLE
  2818.         MTINFILE=""
  2819.         MTSOURCE="--chanid $CHANID --starttime $STARTTIME"
  2820.         hascutlist $CHANID $STARTTIME && MTSOURCE="--honorcutlist $MTSOURCE"
  2821.         scriptlog INFO "$CHANID $STARTTIME matches $META_ARTIST - $TITLE - $SUBTITLE ($INPUT)"
  2822.     else
  2823.         echo "$INPUT" | grep '^\/' >/dev/null 2>&1 || INPUT="`pwd`/${INPUT}"
  2824.         MTINFILE="--infile"
  2825.         MTSOURCE="$INPUT"
  2826.     fi
  2827.  
  2828.     if [ ! -f "$INPUT" ]
  2829.     then
  2830.         scriptlog ERROR "Skipping $INPUT does not exist."
  2831.         scriptlog BREAK
  2832.         unset CHANID STARTTIME
  2833.         continue
  2834.     fi
  2835.  
  2836.     if echo "$INPUT" | grep -v '\.[nm][up][vg]$' >/dev/null 2>&1
  2837.     then
  2838.         scriptlog ERROR "Skipping $INPUT not a nuv or mpg file."
  2839.         scriptlog BREAK
  2840.         unset CHANID STARTTIME
  2841.         continue
  2842.     fi
  2843.  
  2844.     OUTBASE=$(echo "$INPUT" | sed -e 's/\.[nm][up][vg]$//')
  2845.     OUTPUT="${OUTBASE}.${CONTYPE}"
  2846.     if [ -f "$OUTPUT" ]
  2847.     then
  2848.         scriptlog ERROR "Skipping $INPUT. $OUTPUT already exists."
  2849.         scriptlog BREAK
  2850.         unset CHANID STARTTIME
  2851.         continue
  2852.     fi
  2853.  
  2854.     INSIZE=$(( `stat -c %s "${INPUT}"` / 1024 ))
  2855.     FREESPACE=$(df -k --portability "$INPUT" | awk 'END {print $3}')
  2856.     if [ $(( $FREESPACE - $INSIZE )) -lt 10000 ]
  2857.     then
  2858.         scriptlog ERROR "Stopping due to disk space shortage."
  2859.         scriptlog BREAK
  2860.         break
  2861.     fi
  2862.  
  2863.     [ "$QUICKTIME_MP4" = "YES" ] && X264_OPTS="$X264EXT_OPTS"
  2864.  
  2865.     FILEINFO=$(getvidinfo "$INPUT" 0 width height fps scan_type)
  2866.     OLDIFS="$IFS"; IFS=":"; set - $FILEINFO; IFS="$OLDIFS"
  2867.     INWIDTH="$1"; INHEIGHT="$2"; INFPS="$3"; SCANTYPE="$4";
  2868.     if [ "$#" -ne 4 ]
  2869.     then
  2870.         scriptlog ERROR "Skipping $INPUT. Could not obtain vid format details Width $INWIDTH Height $INHEIGHT fps $INFPS ScanType $SCANTYPE"
  2871.         scriptlog BREAK
  2872.         unset CHANID STARTTIME
  2873.         continue
  2874.     fi
  2875.  
  2876.     if [ "$INWIDTH" = 720 -a "$INHEIGHT" = 576 ]
  2877.     then
  2878.         if [ "$SCANTYPE" = "Progressive" ]
  2879.         then
  2880.             FORMAT="576p"
  2881.         elif [ "$SCANTYPE" = "Interlaced" ]
  2882.         then
  2883.             FORMAT="576i"
  2884.         else
  2885.             FORMAT="576i or 576p"
  2886.         fi
  2887.     elif [ "$INWIDTH" = 720 -a "$INHEIGHT" = 480 ]
  2888.     then
  2889.         if [ "$SCANTYPE" = "Progressive" ]
  2890.         then
  2891.             FORMAT="480p"
  2892.         elif [ "$SCANTYPE" = "Interlaced" ]
  2893.         then
  2894.             FORMAT="480i"
  2895.         else
  2896.             FORMAT="480i or 480p"
  2897.         fi
  2898.     elif [ "$INWIDTH" = 1280 -a "$INHEIGHT" = 720 ]
  2899.     then
  2900.         SCANTYPE="Progressive" # Only set if mediainfo available
  2901.         FORMAT="720p"
  2902.     elif [ "$INWIDTH" = 1440 -a "$INHEIGHT" = 1088 ]
  2903.     then
  2904.         if [ "$SCANTYPE" = "Progressive" ]
  2905.         then
  2906.             FORMAT="1080p"
  2907.         elif [ "$SCANTYPE" = "Interlaced" ]
  2908.         then
  2909.             FORMAT="1080i"
  2910.         else
  2911.             FORMAT="1080i or 1080p"
  2912.         fi
  2913.     elif [ "$INWIDTH" = 1920 -a "$INHEIGHT" = 1088 ]
  2914.     then
  2915.         if [ "$SCANTYPE" = "Progressive" ]
  2916.         then
  2917.             FORMAT="1080p"
  2918.         elif [ "$SCANTYPE" = "Interlaced" ]
  2919.         then
  2920.             FORMAT="1080i"
  2921.         else
  2922.             FORMAT="1080i or 1080p"
  2923.         fi
  2924.     else
  2925.         FORMAT="Unknown"
  2926.     fi
  2927.  
  2928.     ASPECTSTR="NA";ASPECTFOUNDIN="NA"
  2929.     if [ "$ASPECTINLINE" = "4:3" -o "$ASPECTINLINE" = "16:9" ]
  2930.     then
  2931.         ASPECTSTR="$ASPECTINLINE"
  2932.         ASPECTFOUNDIN="Command Line"
  2933.     else
  2934.         TMP=$(getaspect "$INPUT")
  2935.         ASPECTSTR=$(echo "$TMP" | cut -d',' -f1)
  2936.         ASPECTFOUNDIN=$(echo "$TMP" | cut -d',' -f2)
  2937.     fi
  2938.     if [ "$ASPECTSTR" != "4:3" -a "$ASPECTSTR" != "16:9" ]
  2939.     then
  2940.         scriptlog ERROR "Skipping $INPUT. Aspect is $ASPECTSTR must be 16:9 or 4:3."
  2941.         scriptlog ERROR "If this is a mpg file make sure to set DEFAULTMPEG2ASPECT at top of this script."
  2942.         scriptlog BREAK
  2943.         unset CHANID STARTTIME
  2944.         continue
  2945.     fi
  2946.     scriptlog INFO "$FORMAT ${INWIDTH}x${INHEIGHT} $SCANTYPE $ASPECTSTR (Found in $ASPECTFOUNDIN) $INFPS FPS"
  2947.  
  2948.     i=0
  2949.     OLDTRACKS=$ATRACKS
  2950.     ATRACKS=""
  2951.     for ATRACK in ${OLDTRACKS//,/ }
  2952.     do
  2953.         set - ${ATRACK/:/ }
  2954.         ATRACK[$i]="$1"
  2955.         INALANG[$i]="$2"
  2956.         FILEINFO=$(getvidinfo "$INPUT" ${ATRACK[$i]} audio_format audio_sample_rate audio_channels audio_resolution audio_language)
  2957.         OLDIFS="$IFS"; IFS=":"; set - $FILEINFO; IFS="$OLDIFS"
  2958.         FORMAT="$1"; INARATE[$i]="$2"; CHANNELS[$i]="$3"; MGF_AUDIO_RESOLUTION[$i]="$4"; [ -z "${INALANG[$i]}" ] && INALANG[$i]="$5"
  2959.         if [ "$#" -ne 5 ]
  2960.         then
  2961.             scriptlog ERROR "Skipping $INPUT. Could not obtain aud format details Language ${INALANG[$i]} ARate ${INARATE[$i]} Channels ${CHANNELS[$i]} ASamplingRate ${MGF_AUDIO_RESOLUTION[$i]}"
  2962.             scriptlog BREAK
  2963.             unset CHANID STARTTIME
  2964.             continue
  2965.         fi
  2966.         scriptlog INFO "$FORMAT Language ${INALANG[$i]} Audio Rate ${INARATE[$i]} Channels ${CHANNELS[$i]} ASamplingRate ${MGF_AUDIO_RESOLUTION[$i]}"
  2967.         [ -n "$ATRACKS" ] && ATRACKS=$ATRACKS,
  2968.         ATRACKS=${ATRACKS}${ATRACK[$i]}
  2969.         [ "${INALANG[$i]}" != "NA" ] && ATRACKS=${ATRACKS}:${INALANG[$i]}
  2970.    
  2971.         # Audio resolution
  2972.         OGG_AUDIO_RESOLUTION[$i]=""
  2973.         FAAC_AUDIO_RESOLUTION[$i]=""
  2974.         if echo "${MGF_AUDIO_RESOLUTION[$i]}" | egrep '^[0-9]+$' >/dev/null 2>&1
  2975.         then
  2976.             OGG_AUDIO_RESOLUTION="--raw-bits=${MGF_AUDIO_RESOLUTION[$i]}"
  2977.             FAAC_AUDIO_RESOLUTION="-B ${MGF_AUDIO_RESOLUTION[$i]}"
  2978.         fi
  2979.    
  2980.         # Channel mapping
  2981.         FAACCCOPT[$i]=""
  2982.         case "${CHANNELS[$i]}" in
  2983.             1*|2*|3*|4*) true ;;
  2984.             5*|6*) FAACCCOPT[$i]="$FAACCHANCONFIG" ;;
  2985.             *) scriptlog ERROR "Audio channels ${CHANNELS[$i]} invalid."
  2986.                scriptlog BREAK
  2987.                unset CHANID STARTTIME
  2988.                continue
  2989.             ;;
  2990.         esac
  2991.         let i=i+1
  2992.     done
  2993.     scriptlog DEBUG "Audio track definitions: $ATRACKS"
  2994.  
  2995.     # Aspect/Scale/Crop opts
  2996.     if [ "$ASPECTSTR" = "4:3" ]
  2997.     then
  2998.         ASPECT=1.333333333
  2999.         SCALE=$SCALE43
  3000.         if [ "$SCALE" = "NA" ]
  3001.         then
  3002.             scriptlog ERROR "Skipping $INPUT Aspect 4:3 which is not supported for quality $QLEVEL"
  3003.             scriptlog BREAK
  3004.             unset CHANID STARTTIME
  3005.             continue
  3006.         fi
  3007.     elif [ "$ASPECTSTR" = "16:9" ]
  3008.     then
  3009.         ASPECT=1.77777777778
  3010.         SCALE=$SCALE169
  3011.     fi
  3012.     SCALESTR=$( echo $SCALE | tr ':' 'x' )
  3013.     SCALEMEN="scale=${SCALE},"
  3014.  
  3015.     OLDIFS="$IFS"; IFS=":"; set - $SCALE; IFS="$OLDIFS"
  3016.     OUTWIDTH="$1"; OUTHEIGHT="$2"
  3017.     if [ "$OUTWIDTH" = "$INWIDTH" -a "$OUTHEIGHT" = "$INHEIGHT" ]
  3018.     then
  3019.         CROPSCALE=""
  3020.         scriptlog INFO "Input and Output same resolution. crop,scale disabled."
  3021.     elif echo "$CROP" | egrep -i 'ON|YES' >/dev/null 2>&1
  3022.     then
  3023.         if [ "$OUTWIDTH" -gt "$INWIDTH" -o "$OUTHEIGHT" -gt "$INHEIGHT" ]
  3024.         then
  3025.             scriptlog INFO "Output is a greater scale than input. This is not sensible."
  3026.         fi
  3027.         CROPX=$CROPSIZE
  3028.         CROPY=$CROPSIZE
  3029.         CROPW=$(( $INWIDTH - ( 2 * $CROPX ) ))
  3030.         CROPH=$(( $INHEIGHT - ( 2 * $CROPY ) ))
  3031.         CROPVAL="${CROPW}:${CROPH}:${CROPX}:${CROPY}"
  3032.         CROPMEN="crop=${CROPVAL},"
  3033.         CROPSCALE="${CROPMEN}${SCALEMEN}"
  3034.         scriptlog INFO "Crop to $CROPVAL. Scale to $SCALESTR."
  3035.     else
  3036.         CROPSCALE="${SCALEMEN}"
  3037.         scriptlog INFO "Scale to $SCALESTR."
  3038.     fi
  3039.  
  3040.     # Filter opts
  3041.     OUTFPS="$INFPS" ; MENOUTFPS=""
  3042.     POSTVIDFILTERS=$(echo ${POSTVIDFILTERS} | sed -e 's/'"${INVTELECINEFILTER}"',//')
  3043.     POSTVIDFILTERS=$(echo ${POSTVIDFILTERS} | sed -e 's/'"${DEINTERLACEFILTER}"',//')
  3044.     [ -n "$CHANID" ] && SOURCENAME=$(getsourcename $CHANID)
  3045.     # Progressive then skip Deinterlace/Invtelecine
  3046.     if echo $INFPS | egrep '^23|^24' >/dev/null 2>&1
  3047.     then
  3048.         # Keep 23.976 FPS otherwise mencoder will convert to 29.97
  3049.         OUTFPS="23.976"
  3050.         scriptlog INFO "Input $INFPS FPS. OUTFPS set to $OUTFPS. Deinterlace/Invtelecine filter not needed."
  3051.     elif [ "$SCANTYPE" = "Progressive" ]
  3052.     then
  3053.         scriptlog INFO "$SCANTYPE. Deinterlace/Invtelecine filter not needed."
  3054.     # Deinterlace options
  3055.     elif echo "$DEINTERLACE" | egrep -i 'ON|YES' >/dev/null 2>&1
  3056.     then
  3057.         POSTVIDFILTERS="${POSTVIDFILTERS}${DEINTERLACEFILTER},"
  3058.         scriptlog INFO "Deinterlace filter added."
  3059.         [ "$SCANTYPE" != "Interlaced" ] && scriptlog INFO "If progressive this is wrong use --deinterlace=NO."
  3060.         echo "$INFPS" | grep  '^29' >/dev/null 2>&1 &&
  3061.             scriptlog INFO "You may need Invtelecine rather than Deinterlace. (--deinterlace=NO --invtelecine=YES)."
  3062.     elif [ -n "$SOURCENAME" ] && echo "$DEINTERLACE" | grep -i "$SOURCENAME" >/dev/null 2>&1
  3063.     then
  3064.         POSTVIDFILTERS="${POSTVIDFILTERS}${DEINTERLACEFILTER},"
  3065.         scriptlog INFO "Source $SOURCENAME. Deinterlace filter added."
  3066.         [ "$SCANTYPE" != "Interlaced" ] && scriptlog INFO "If progressive this is wrong use --deinterlace=NO."
  3067.         echo "$INFPS" | grep  '^29' >/dev/null 2>&1 &&
  3068.             scriptlog INFO "You may need Invtelecine rather than Deinterlace. (--deinterlace=NO --invtelecine=YES)."
  3069.     # Invtelecine options
  3070.     elif echo "$INVTELECINE" | egrep -i 'ON|YES' >/dev/null 2>&1 && echo $INFPS | egrep '^24|^25' >/dev/null 2>&1
  3071.     then
  3072.         # Very unusual to have PAL/DVB telecine video
  3073.         scriptlog INFO "Input $INFPS FPS. Invtelecine filter not supported."
  3074.     elif echo "$INVTELECINE" | egrep -i 'ON|YES' >/dev/null 2>&1
  3075.     then
  3076.         POSTVIDFILTERS="${POSTVIDFILTERS}${INVTELECINEFILTER},"
  3077.         OUTFPS="23.976"
  3078.         scriptlog INFO "Invtelecine filter added."
  3079.     fi
  3080.     [ "$OUTFPS" = "23.976" ] && MENOUTFPS="-ofps 24000/1001"
  3081.     [ -n "$POSTVIDFILTERS" ] && POSTVIDFILTERS="${POSTVIDFILTERS}softskip,"
  3082.  
  3083.     # Encoder opts
  3084.     # Force avi for videos staying in MythRecord
  3085.     if [ "$CONTYPE" = "avi" ] || [ -n "$CHANID" -a -z "$COPYDIR" ]
  3086.     then
  3087.         if [ "$AVIVID" = "xvid" ]
  3088.         then
  3089.             VBITRATE=$(calcbitrate $ASPECT $SCALE $XVID_CQ)
  3090.             PASSCMD="pass"
  3091.             VIDEOCODEC="-ovc xvid -xvidencopts ${XVID_OPTS}:bitrate=${VBITRATE}"
  3092.             VIDEXT="xvid"
  3093.         elif [ "$AVIVID" = "lavc" ]
  3094.         then
  3095.             VBITRATE=$(calcbitrate $ASPECT $SCALE $LAVC_CQ)
  3096.             PASSCMD="vpass"
  3097.             VIDEOCODEC="-ovc lavc -lavcopts ${LAVC_OPTS}:vbitrate=${VBITRATE}"
  3098.             VIDEXT="lavc"
  3099.         else
  3100.             scriptlog ERROR "Skipping $INPUT. Unsupported avi encoder"
  3101.             scriptlog BREAK
  3102.             unset CHANID STARTTIME
  3103.             continue
  3104.         fi
  3105.         ABITRATE=$MP3_ABITRATE
  3106.         AUDIOCODEC="-oac mp3lame -lameopts vbr=2:br=${ABITRATE}"
  3107.         AUDEXT="mp3"
  3108.         CONTYPE="avi"
  3109.         QUICKTIME_MP4="NO"
  3110.         MENOUT1STPASS="-aspect $ASPECT -force-avi-aspect $ASPECTSTR -o /dev/null"
  3111.         MENOUTOPT="-aspect $ASPECT -force-avi-aspect $ASPECTSTR -o"
  3112.         MENOUTFILE="$OUTPUT"
  3113.         MTOPT="--audiotrack ${ATRACKS:0:1}"
  3114.     elif [ "$CONTYPE" = "mp4" ]
  3115.     then
  3116.         VBITRATE=$(calcbitrate $ASPECT $SCALE $X264_CQ)
  3117.         AQUAL=$AAC_AQUAL
  3118.         PASSCMD="pass"
  3119.         VIDEOCODEC="-ovc x264 -x264encopts ${X264_OPTS}:bitrate=${VBITRATE}"
  3120.         VIDEXT="h264"
  3121.         AUDIOCODEC="-oac copy"
  3122.         AUDEXT="aac"
  3123.         MENOUT1STPASS="-of rawvideo -o /dev/null"
  3124.         MENOUTOPT="-of rawvideo -o"
  3125.         MENOUTFILE="${OUTBASE}_video.h264"
  3126.     elif [ "$CONTYPE" = "mkv" ]
  3127.     then
  3128.         VBITRATE=$(calcbitrate $ASPECT $SCALE $X264_CQ)
  3129.         if [ "$MKVAUD" = "ogg" ]
  3130.         then
  3131.             AQUAL=$OGG_AQUAL
  3132.             AUDEXT="ogg"
  3133.         elif [ "$MKVAUD" = "aac" ]
  3134.         then
  3135.             AQUAL=$AAC_AQUAL
  3136.             AUDEXT="aac"
  3137.         else
  3138.             scriptlog ERROR "Skipping $INPUT. Unsupported audio encoder"
  3139.             scriptlog BREAK
  3140.             unset CHANID STARTTIME
  3141.             continue
  3142.         fi
  3143.         PASSCMD="pass"
  3144.         VIDEOCODEC="-ovc x264 -x264encopts ${X264_OPTS}:bitrate=${VBITRATE}"
  3145.         VIDEXT="h264"
  3146.         AUDIOCODEC="-oac copy"
  3147.         MENOUT1STPASS="-of rawvideo -o /dev/null"
  3148.         MENOUTOPT="-of rawvideo -o"
  3149.         MENOUTFILE="${OUTBASE}_video.h264"
  3150.     else
  3151.         scriptlog ERROR "Skipping $INPUT. Incorrect video contype selected. $CONTYPE"
  3152.         scriptlog BREAK
  3153.         unset CHANID STARTTIME
  3154.         continue
  3155.     fi
  3156.  
  3157.     RETCODE=0
  3158.     # Fireoff a background monitoring job to update the job queue details
  3159.     [ "$JOBID" -ne 99999999 ] && $CMD --monitor=$JOBID ${$} "$TRANSOP" "$LOGFILE" &
  3160.  
  3161.     # Pause boinc
  3162.     boinccontrol "suspend"
  3163.  
  3164.     #Start time
  3165.     ENCSTARTTIME=$(date +%Y-%m-%d\ %H:%M:%S)
  3166.     ORIGINALFILESIZE=$(du -h "$INPUT" | cut -f1)
  3167.  
  3168.     i=0
  3169.     # mp4/mkv have seperate Audio/Video transcodes.
  3170.     for ATRACK in ${ATRACKS//,/ }
  3171.     do
  3172.         ATRACK=${ATRACK:0:1}
  3173.         MTOPTS="--audiotrack ${ATRACK}"
  3174.         if [ "$AUDEXT" = "aac" ]
  3175.         then
  3176.             if [ ! -f "${OUTBASE}_audio${ATRACK}.${AUDEXT}" ]
  3177.             then
  3178.                 AENCLINE="faac ${FIFODIR}/audout -P ${FAAC_AUDIO_RESOLUTION[$i]} -R ${INARATE[$i]} -C ${CHANNELS[$i]} ${FAACCCOPT[$i]} -c ${INARATE[$i]} -X -q $AQUAL --mpeg-vers 4 -o ${OUTBASE}_audio$ATRACK.${AUDEXT}"
  3179.                 scriptlog INFO "Audio Encoder: $AENCLINE."
  3180.    
  3181.                 scriptlog START "Starting $AUDEXT audio trans of $INPUT, track $ATRACK. quality $AQUAL."
  3182.                 [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] audio pass started"
  3183.    
  3184.                 rm -f "${FIFODIR}"/*out "$TRANSOP" "$MENCODEROP"
  3185.                 if [ -n "$MTINFILE" ]
  3186.                 then
  3187.                     nice -n 19 mythtranscode --profile autodetect $MTINFILE "$MTSOURCE" $MTOPTS --fifodir "$FIFODIR" | tee -a "$TRANSOP" &
  3188.                 else
  3189.                     nice -n 19 mythtranscode --profile autodetect $MTSOURCE $MTOPTS --fifodir "$FIFODIR" | tee -a "$TRANSOP" &
  3190.                 fi
  3191.                 sleep 10
  3192.                 # Throw away video
  3193.                 nice -n 19 dd bs=512k if="${FIFODIR}/vidout" of=/dev/null &
  3194.                 nice -n 19 faac "${FIFODIR}/audout" -P ${FAAC_AUDIO_RESOLUTION[$i]} -R ${INARATE[$i]} -C ${CHANNELS[$i]} ${FAACCCOPT[$i]} -c ${INARATE[$i]} -X -q $AQUAL --mpeg-vers 4 -o "${OUTBASE}_audio$ATRACK.${AUDEXT}"
  3195.                 RETCODE=$?
  3196.                 sleep 10
  3197.                 if [ $RETCODE -ne 0 ]
  3198.                 then
  3199.                     scriptlog ERROR "Skipping $INPUT. Problem with audio pass."
  3200.                     scriptlog BREAK
  3201.                     unset CHANID STARTTIME
  3202.                     continue
  3203.                 fi
  3204.             else
  3205.                 scriptlog INFO "Track $ATRACK Audio Encoding already done"
  3206.             fi
  3207.         elif [ "$AUDEXT" = "ogg" ]
  3208.         then
  3209.             if [ ! -f "${OUTBASE}_audio$ATRACK.${AUDEXT}" ]
  3210.             then
  3211.                 AENCLINE="oggenc ${OGG_AUDIO_RESOLUTION[$i]} --raw-chan=${CHANNELS[$i]} --raw-rate=${INARATE[$i]} --quality=${AQUAL} -o ${OUTBASE}_audio$ATRACK.${AUDEXT} ${FIFODIR}/audout"
  3212.                 scriptlog INFO "Audio Encoder: $AENCLINE."
  3213.    
  3214.                 scriptlog START "Starting $AUDEXT audio trans of $INPUT. quality $AQUAL."
  3215.                 [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] audio pass started"
  3216.    
  3217.                 rm -f "${FIFODIR}"/*out "$TRANSOP" "$MENCODEROP"
  3218.                 if [ -n "$MTINFILE" ]
  3219.                 then
  3220.                     nice -n 19 mythtranscode --profile autodetect $MTINFILE "$MTSOURCE" $MTOPTS --fifodir "$FIFODIR" | tee -a "$TRANSOP" &
  3221.                 else
  3222.                     nice -n 19 mythtranscode --profile autodetect $MTSOURCE $MTOPTS --fifodir "$FIFODIR" | tee -a "$TRANSOP" &
  3223.                 fi
  3224.                 sleep 10
  3225.                 # Throw away video
  3226.                 nice -n 19 dd bs=512k if="${FIFODIR}/vidout" of=/dev/null &
  3227.                 nice -n 19 oggenc ${OGG_AUDIO_RESOLUTION[$i]} --raw-chan=${CHANNELS[$i]} --raw-rate=${INARATE[$i]} --quality=${AQUAL} -o "${OUTBASE}_audio$ATRACK.${AUDEXT}" "${FIFODIR}/audout"
  3228.                 RETCODE=$?
  3229.                 sleep 10
  3230.                 if [ $RETCODE -ne 0 ]
  3231.                 then
  3232.                     scriptlog ERROR "Skipping $INPUT. Problem with audio pass."
  3233.                     scriptlog BREAK
  3234.                     unset CHANID STARTTIME
  3235.                     continue
  3236.                 fi
  3237.             else
  3238.                 scriptlog INFO "Track $ATRACK Audio Encoding already done"
  3239.             fi
  3240.         fi
  3241.         let i=i+1
  3242.     done
  3243.  
  3244.     if [ "$PASS" = "one" ]
  3245.     then
  3246.         if [ ! -f "$MENOUTFILE" ]
  3247.         then
  3248.             VENCLINE="mencoder -idx -noskip \
  3249.             ${FIFODIR}/vidout -demuxer rawvideo -rawvideo w=${INWIDTH}:h=${INHEIGHT}:fps=${INFPS} \
  3250.             -audiofile ${FIFODIR}/audout -audio-demuxer rawaudio -rawaudio rate=${INARATE}:channels=${CHANNELS} \
  3251.             ${VIDEOCODEC} \
  3252.             ${AUDIOCODEC} \
  3253.             -vf ${POSTVIDFILTERS}${CROPSCALE}${ENDVIDFILTERS}harddup -sws 7 $MENOUTFPS \
  3254.             $MENOUTOPT $MENOUTFILE"
  3255.             scriptlog INFO "Video Encoder: $VENCLINE."
  3256.  
  3257.             scriptlog START "Starting $VIDEXT Single video pass trans of $INPUT. vbr $VBITRATE abr $ABITRATE."
  3258.             [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] Single video pass started."
  3259.  
  3260.             rm -f "${FIFODIR}"/*out "$TRANSOP" "$MENCODEROP"
  3261.             if [ -n "$MTINFILE" ]
  3262.             then
  3263.                 nice -n 19 mythtranscode --profile autodetect $MTINFILE "$MTSOURCE" --fifodir "$FIFODIR" | tee -a "$TRANSOP" &
  3264.             else
  3265.                 nice -n 19 mythtranscode --profile autodetect $MTSOURCE --fifodir "$FIFODIR" | tee -a "$TRANSOP" &
  3266.             fi
  3267.             sleep 10
  3268.             nice -n 19 mencoder -idx -noskip \
  3269.             "${FIFODIR}/vidout" -demuxer rawvideo -rawvideo w=${INWIDTH}:h=${INHEIGHT}:fps=${INFPS} \
  3270.             -audiofile "${FIFODIR}/audout" -audio-demuxer rawaudio -rawaudio rate=${INARATE}:channels=${CHANNELS} \
  3271.             ${VIDEOCODEC} \
  3272.             ${AUDIOCODEC} \
  3273.             -vf ${POSTVIDFILTERS}${CROPSCALE}${ENDVIDFILTERS}harddup -sws 7 $MENOUTFPS \
  3274.             $MENOUTOPT "$MENOUTFILE" | tee -a "$MENCODEROP"
  3275.             RETCODE=$?
  3276.             sleep 10
  3277.         else
  3278.             scriptlog INFO "Video Encoding already done"
  3279.         fi
  3280.     else
  3281.         if [ ! -f "$MENOUTFILE" ]
  3282.         then
  3283.             VENCLINE="mencoder -idx \
  3284.             ${FIFODIR}/vidout -demuxer rawvideo -rawvideo w=${INWIDTH}:h=${INHEIGHT}:fps=${INFPS} \
  3285.             -audiofile ${FIFODIR}/audout -audio-demuxer rawaudio -rawaudio rate=${INARATE}:channels=${CHANNELS} \
  3286.             ${VIDEOCODEC}:${PASSCMD}=1:turbo -passlogfile ${FIFODIR}/2pass.log \
  3287.             ${AUDIOCODEC} \
  3288.             -vf ${POSTVIDFILTERS}${CROPSCALE}${ENDVIDFILTERS}harddup -sws 7 $MENOUTFPS \
  3289.             $MENOUT1STPASS"
  3290.             scriptlog INFO "Video Encoder: $VENCLINE."
  3291.  
  3292.             scriptlog START "Starting $VIDEXT 1st video pass trans of $INPUT. vbr $VBITRATE abr $ABITRATE."
  3293.             [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] 1st video pass started."
  3294.  
  3295.             rm -f "${FIFODIR}"/*out "$TRANSOP" "$MENCODEROP"
  3296.             if [ -n "$MTINFILE" ]
  3297.             then
  3298.                 nice -n 19 mythtranscode --profile autodetect $MTINFILE "$MTSOURCE" --fifodir "$FIFODIR" | tee -a "$TRANSOP" &
  3299.             else
  3300.                 nice -n 19 mythtranscode --profile autodetect $MTSOURCE --fifodir "$FIFODIR" | tee -a "$TRANSOP" &
  3301.             fi
  3302.             sleep 10
  3303.             nice -n 19 mencoder -idx \
  3304.             "${FIFODIR}/vidout" -demuxer rawvideo -rawvideo w=${INWIDTH}:h=${INHEIGHT}:fps=${INFPS} \
  3305.             -audiofile "${FIFODIR}/audout" -audio-demuxer rawaudio -rawaudio rate=${INARATE}:channels=${CHANNELS} \
  3306.             ${VIDEOCODEC}:${PASSCMD}=1:turbo -passlogfile "${FIFODIR}/2pass.log" \
  3307.             ${AUDIOCODEC} \
  3308.             -vf ${POSTVIDFILTERS}${CROPSCALE}${ENDVIDFILTERS}harddup -sws 7 $MENOUTFPS \
  3309.             $MENOUT1STPASS
  3310.             RETCODE=$?
  3311.             sleep 10
  3312.             if [ $RETCODE -ne 0 ]
  3313.             then
  3314.                 scriptlog ERROR "Skipping $INPUT. Problem with 1st video pass of 2."
  3315.                 scriptlog BREAK
  3316.                 unset CHANID STARTTIME
  3317.                 continue
  3318.             fi
  3319.         else
  3320.             scriptlog INFO "Video Encoding already done"
  3321.         fi
  3322.  
  3323.         if [ ! -f "$MENOUTFILE" ]
  3324.         then
  3325.             VENCLINE="mencoder -idx -noskip \
  3326.             ${FIFODIR}/vidout -demuxer rawvideo -rawvideo w=${INWIDTH}:h=${INHEIGHT}:fps=${INFPS} \
  3327.             -audiofile ${FIFODIR}/audout -audio-demuxer rawaudio -rawaudio rate=${INARATE}:channels=${CHANNELS} \
  3328.             ${VIDEOCODEC}:${PASSCMD}=2 -passlogfile ${FIFODIR}/2pass.log \
  3329.             ${AUDIOCODEC} \
  3330.             -vf ${POSTVIDFILTERS}${CROPSCALE}${ENDVIDFILTERS}harddup -sws 7 $MENOUTFPS \
  3331.             $MENOUTOPT $MENOUTFILE"
  3332.             scriptlog INFO "Video Encoder: $VENCLINE."
  3333.  
  3334.             scriptlog START "Starting $VIDEXT 2nd video pass trans of $INPUT. vbr $VBITRATE abr $ABITRATE."
  3335.             [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] 2nd video pass started."
  3336.  
  3337.             rm -f "${FIFODIR}"/*out "$TRANSOP" "$MENCODEROP"
  3338.             if [ -n "$MTINFILE" ]
  3339.             then
  3340.                 nice -n 19 mythtranscode --profile autodetect $MTINFILE "$MTSOURCE" --fifodir "$FIFODIR" | tee -a "$TRANSOP" &
  3341.             else
  3342.                 nice -n 19 mythtranscode --profile autodetect $MTSOURCE --fifodir "$FIFODIR" | tee -a "$TRANSOP" &
  3343.             fi
  3344.             sleep 10
  3345.             nice -n 19 mencoder -idx -noskip \
  3346.             "${FIFODIR}/vidout" -demuxer rawvideo -rawvideo w=${INWIDTH}:h=${INHEIGHT}:fps=${INFPS} \
  3347.             -audiofile "${FIFODIR}/audout" -audio-demuxer rawaudio -rawaudio rate=${INARATE}:channels=${CHANNELS} \
  3348.             ${VIDEOCODEC}:${PASSCMD}=2 -passlogfile "${FIFODIR}/2pass.log" \
  3349.             ${AUDIOCODEC} \
  3350.             -vf ${POSTVIDFILTERS}${CROPSCALE}${ENDVIDFILTERS}harddup -sws 7 $MENOUTFPS \
  3351.             $MENOUTOPT "$MENOUTFILE" | tee -a "$MENCODEROP"
  3352.             RETCODE=$?
  3353.             sleep 10
  3354.         else
  3355.             scriptlog INFO "Video Encoding already done"
  3356.         fi
  3357.     fi
  3358.  
  3359.     if [ $RETCODE -ne 0 ]
  3360.     then
  3361.         scriptlog ERROR "Skipping $INPUT. Problem with final video pass. $OUTPUT may exist."
  3362.         scriptlog BREAK
  3363.         unset CHANID STARTTIME
  3364.         continue
  3365.     fi
  3366.  
  3367.     if [ "$CONTYPE" = "mp4" -o "$CONTYPE" = "mkv" ]
  3368.     then
  3369.         if [ -f "$CHAPTERFILE" ]
  3370.         then
  3371.             scriptlog START "Using chapter file $CHAPTERFILE."
  3372.         elif [ -n "$CHAPTERDURATION" -a "$CHAPTERDURATION" -gt 0 ]
  3373.         then
  3374.             scriptlog START "Generating chapter file."
  3375.             [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] Generating chapter file."
  3376.             CHAPTERFILE=$(genchapfile "${OUTBASE}_audio.${AUDEXT}" $CHAPTERDURATION $CONTYPE)
  3377.             [ -f "$CHAPTERFILE" ] || scriptlog ERROR "Generating chapter failed."
  3378.         fi
  3379.         scriptlog START "Joining ${OUTBASE}_video.h264 ${OUTBASE}_audio.${AUDEXT} in $CONTYPE container."
  3380.         [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] Joining in $CONTYPE container."
  3381.         if ! encloseincontainer "$OUTBASE" $OUTFPS $AUDEXT $CONTYPE $ASPECTSTR $ATRACKS "$TITLE" "$CHAPTERFILE"
  3382.         then
  3383.             scriptlog ERROR "$CONTYPE container Failed for $OUTPUT."
  3384.             scriptlog BREAK
  3385.             unset CHANID STARTTIME
  3386.             continue
  3387.         fi
  3388.     fi
  3389.  
  3390.     scriptlog START "Checking $OUTPUT."
  3391.     [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] Checking result."
  3392.     if ! checkoutput "$INPUT" "$OUTPUT" "$MENCODEROP" "$OUTPUTCHECKS"
  3393.     then
  3394.         mv "$OUTPUT" "${OUTPUT}-SUSPECT"
  3395.         scriptlog ERROR "$OUTPUT may be faulty. Saved as ${OUTPUT}-SUSPECT. $INPUT kept."
  3396.         scriptlog BREAK
  3397.         unset CHANID STARTTIME
  3398.         continue
  3399.     fi
  3400.  
  3401.     if [ -n "$CHANID" ]
  3402.     then
  3403.         SEARCHTITLE=$(getsearchtitle "$CHANID" "$STARTTIME")
  3404.         is21orless && INETREF=$(lookupinetref "$SEARCHTITLE" "$CHANID" "$STARTTIME") || INETREF="00000000"
  3405.         SERIESEPISODE=$(getseriesepisode "$CHANID" "$STARTTIME" "$INETREF")
  3406.         FILENAME=$(createfiletitleSEsubtitle "$CHANID" "$STARTTIME" "$SERIESEPISODE")
  3407.     else
  3408.         FILENAME=$(basename "$OUTPUT" | sed -e 's/\.[am][vkp][iv4]$//')
  3409.     fi
  3410.  
  3411.     if [ -n "$COPYDIR" ]
  3412.     then
  3413.         # Is this a good idea?
  3414.         #CATEGORY=$(getcategory "$CHANID" "$STARTTIME")
  3415.         #[ -n "$CATEGORY" ]
  3416.         #then
  3417.         #   COPYDIR="${COPYDIR}/${CATEGORY}"
  3418.         #fi
  3419.         [ -d "$(dirname "$COPYDIR/$FILENAME")" ] || mkdir -p "$(dirname "$COPYDIR/$FILENAME")"
  3420.         NEWNAME="$FILENAME"
  3421.         while [ -f "${COPYDIR}/${NEWNAME}.${CONTYPE}" ]
  3422.         do
  3423.             COUNT=$(( ${COUNT:=0} + 1 ))
  3424.             NEWNAME="${FILENAME}_${COUNT}"
  3425.         done
  3426.         FILENAME="${NEWNAME}.${CONTYPE}"
  3427.         if cp "$OUTPUT" "${COPYDIR}/${FILENAME}"
  3428.         then
  3429.             rm -f "$OUTPUT"
  3430.             scriptlog SUCCESS "Successful trans. $INPUT trans to ${COPYDIR}/${FILENAME}. $INPUT kept"
  3431.             if [ "$QUICKTIME_MP4" = "YES" ]
  3432.             then
  3433.                 OLDFILE="${COPYDIR}/${FILENAME}"
  3434.                 FILENAME=$(echo "$FILENAME" | sed -e 's/mp4$/mov/')
  3435.                 mv "$OLDFILE" "${COPYDIR}/${FILENAME}"
  3436.             fi
  3437.             if is21orless
  3438.             then
  3439.                 MYTHVIDDIR=$(getsetting VideoStartupDir)
  3440.                 if echo "$COPYDIR" | grep "$MYTHVIDDIR" >/dev/null 2>&1
  3441.                 then
  3442.                     createvideometadata "${COPYDIR}/${FILENAME}" "$TITLE" "$ASPECTSTR" "$CHANID" "$STARTTIME" "$INETREF" "$SERIESEPISODE"
  3443.                 fi
  3444.             else
  3445.                 scriptlog INFO "MythTV V0.22 or greater. Not creating MythVideo entry. Use MythVideo menu"
  3446.             fi
  3447.             if echo "$DELETEREC" | egrep -i 'ON|YES' >/dev/null 2>&1 && [ "$FINALEXIT" -eq 0 ]
  3448.             then
  3449.                 scriptlog INFO "Deleting recording."
  3450.                 deleterecording "$CHANID" "$STARTTIME"
  3451.             fi
  3452.             NEWFILESIZE=$(du -h "${COPYDIR}/${FILENAME}" | cut -f1)
  3453.         else
  3454.             scriptlog ERROR "Successful trans but copy to ${COPYDIR}/${FILENAME} bad. $INPUT trans to $OUTPUT. $INPUT kept"
  3455.         fi
  3456.     else
  3457.         if [ -n "$CHANID" ]
  3458.         then
  3459.             scriptlog INFO "Updating MythRecord db to $OUTPUT."
  3460.             updatemetadata "$OUTPUT" "$CHANID" "$STARTTIME"
  3461.             # mythcommflag --rebuild does not work correctly for avi files.
  3462.             # Without this you can't edit files, but with it seeks don't work correctly.
  3463.             #scriptlog INFO "Rebuilding seektable for $OUTPUT."
  3464.             #mythcommflag --chanid "$CHANID" --starttime "$STARTTIME" --rebuild >/dev/null
  3465.             rm -f "${INPUT}.png"
  3466.         fi
  3467.         if [ "$DEBUG" = "ON" -o "$SAVENUV" = "ON" ]
  3468.         then
  3469.             mv "$INPUT" "${INPUT}OK-DONE"
  3470.             scriptlog SUCCESS "Successful trans to $OUTPUT. $INPUT moved to ${INPUT}OK-DONE."
  3471.         else
  3472.             rm -f "$INPUT"
  3473.             scriptlog SUCCESS "Successful trans to $OUTPUT. $INPUT removed."
  3474.         fi
  3475.         NEWFILESIZE=$(du -h "$OUTPUT" | cut -f1)
  3476.     fi
  3477.     # End time
  3478.     ENCENDTIME=$(date +%Y-%m-%d\ %H:%M:%S)
  3479.     logtranstime "$ENCSTARTTIME" "$ENCENDTIME" "$ORIGINALFILESIZE" "$NEWFILESIZE"
  3480.     scriptlog BREAK
  3481.     recall
  3482.     unset CHANID STARTTIME
  3483. done
  3484. exit $FINALEXIT
  3485.  
  3486.  
  3487. #STARTNUVINFO
  3488. #!/usr/bin/perl
  3489. # $Date: 2010/10/09 21:06:19 $
  3490. # $Revision: 1.61 $
  3491. # $Author: mythtv $
  3492. #
  3493. #  mythtv::nuvinfo.pm
  3494. #
  3495. #   exports one routine:  nuv_info($path_to_nuv)
  3496. #   This routine inspects a specified nuv file, and returns information about
  3497. #   it, gathered either from its nuv file structure
  3498. #
  3499. # Auric grabbed from nuvexport and Modified. Thanks to the nuvexport guys, I never would have been able to work this out
  3500. #
  3501. # finfo version width height desiredheight desiredwidth pimode aspect fps videoblocks audioblocks textsblocks keyframedist video_type audio_type audio_sample_rate audio_bits_per_sample audio_channels audio_compression_ratio audio_quality rtjpeg_quality rtjpeg_luma_filter rtjpeg_chroma_filter lavc_bitrate lavc_qmin lavc_qmax lavc_maxqdiff seektable_offset keyframeadjust_offset
  3502.  
  3503. # Byte swap a 32-bit number from little-endian to big-endian
  3504.     sub byteswap32 {
  3505.        # Read in a 4-character string
  3506.        my $in = shift;
  3507.        my $out = $in;
  3508.  
  3509.        if ($Config{'byteorder'} == 4321) {
  3510.            substr($out, 0, 1) = substr($in, 3, 1);
  3511.            substr($out, 3, 1) = substr($in, 0, 1);
  3512.            substr($out, 1, 1) = substr($in, 2, 1);
  3513.            substr($out, 2, 1) = substr($in, 1, 1);
  3514.        }
  3515.  
  3516.        return $out;
  3517.     }
  3518.  
  3519. # Byte swap a 64-bit number from little-endian to big-endian
  3520.     sub byteswap64 {
  3521.        # Read in a 8-character string
  3522.        my $in = shift;
  3523.        my $out = $in;
  3524.  
  3525.        if ($Config{'byteorder'} == 4321) {
  3526.            substr($out, 4, 4) = byteswap32(substr($in, 0, 4));
  3527.            substr($out, 0, 4) = byteswap32(substr($in, 4, 4));
  3528.        }
  3529.  
  3530.        return $out;
  3531.     }
  3532.  
  3533. # Opens a .nuv file and returns information about it
  3534.     sub nuv_info {
  3535.         my $file = shift;
  3536.         my(%info, $buffer);
  3537.     # open the file
  3538.         open(DATA, $file) or die "Can't open $file:  $!\n\n";
  3539.     # Read the file info header
  3540.         read(DATA, $buffer, 72);
  3541.     # Byte swap the buffer
  3542.         if ($Config{'byteorder'} == 4321) {
  3543.             substr($buffer, 20, 4) = byteswap32(substr($buffer, 20, 4));
  3544.             substr($buffer, 24, 4) = byteswap32(substr($buffer, 24, 4));
  3545.             substr($buffer, 28, 4) = byteswap32(substr($buffer, 28, 4));
  3546.             substr($buffer, 32, 4) = byteswap32(substr($buffer, 32, 4));
  3547.             substr($buffer, 40, 8) = byteswap64(substr($buffer, 40, 8));
  3548.             substr($buffer, 48, 8) = byteswap64(substr($buffer, 48, 8));
  3549.             substr($buffer, 56, 4) = byteswap32(substr($buffer, 56, 4));
  3550.             substr($buffer, 60, 4) = byteswap32(substr($buffer, 60, 4));
  3551.             substr($buffer, 64, 4) = byteswap32(substr($buffer, 64, 4));
  3552.             substr($buffer, 68, 4) = byteswap32(substr($buffer, 68, 4));
  3553.         }
  3554.     # Unpack the data structure
  3555.         ($info{'finfo'},          # "NuppelVideo" + \0
  3556.          $info{'version'},        # "0.05" + \0
  3557.          $info{'width'},
  3558.          $info{'height'},
  3559.          $info{'desiredheight'},  # 0 .. as it is
  3560.          $info{'desiredwidth'},   # 0 .. as it is
  3561.          $info{'pimode'},         # P .. progressive, I .. interlaced  (2 half pics) [NI]
  3562.          $info{'aspect'},         # 1.0 .. square pixel (1.5 .. e.g. width=480: width*1.5=720 for capturing for svcd material
  3563.          $info{'fps'},
  3564.          $info{'videoblocks'},    # count of video-blocks -1 .. unknown   0 .. no video
  3565.          $info{'audioblocks'},    # count of audio-blocks -1 .. unknown   0 .. no audio
  3566.          $info{'textsblocks'},    # count of text-blocks  -1 .. unknown   0 .. no text
  3567.          $info{'keyframedist'}
  3568.             ) = unpack('Z12 Z5 xxx i i i i a xxx d d i i i i', $buffer);
  3569.     # Perl occasionally over-reads on the previous read()
  3570.         seek(DATA, 72, 0);
  3571.     # Read and parse the first frame header
  3572.         read(DATA, $buffer, 12);
  3573.     # Byte swap the buffer
  3574.         if ($Config{'byteorder'} == 4321) {
  3575.             substr($buffer, 4, 4) = byteswap32(substr($buffer, 4, 4));
  3576.             substr($buffer, 8, 4) = byteswap32(substr($buffer, 8, 4));
  3577.         }
  3578.         my ($frametype,
  3579.             $comptype,
  3580.             $keyframe,
  3581.             $filters,
  3582.             $timecode,
  3583.             $packetlength) = unpack('a a a a i i', $buffer);
  3584.     # Parse the frame
  3585.         die "Illegal nuv file format:  $file\n\n" unless ($frametype eq 'D');
  3586.     # Read some more stuff if we have to
  3587.         read(DATA, $buffer, $packetlength) if ($packetlength);
  3588.     # Read the remaining frame headers
  3589.         while (12 == read(DATA, $buffer, 12)) {
  3590.         # Byte swap the buffer
  3591.             if ($Config{'byteorder'} == 4321) {
  3592.                 substr($buffer, 4, 4) = byteswap32(substr($buffer, 4, 4));
  3593.                 substr($buffer, 8, 4) = byteswap32(substr($buffer, 8, 4));
  3594.             }
  3595.         # Parse the frame header
  3596.             ($frametype,
  3597.              $comptype,
  3598.              $keyframe,
  3599.              $filters,
  3600.              $timecode,
  3601.              $packetlength) = unpack('a a a a i i', $buffer);
  3602.         # Read some more stuff if we have to
  3603.             read(DATA, $buffer, $packetlength) if ($packetlength);
  3604.         # Look for the audio frame
  3605.             if ($frametype eq 'X') {
  3606.             # Byte swap the buffer
  3607.                 if ($Config{'byteorder'} == 4321) {
  3608.                     substr($buffer, 0, 4)  = byteswap32(substr($buffer, 0, 4));
  3609.                     substr($buffer, 12, 4) = byteswap32(substr($buffer, 12, 4));
  3610.                     substr($buffer, 16, 4) = byteswap32(substr($buffer, 16, 4));
  3611.                     substr($buffer, 20, 4) = byteswap32(substr($buffer, 20, 4));
  3612.                     substr($buffer, 24, 4) = byteswap32(substr($buffer, 24, 4));
  3613.                     substr($buffer, 28, 4) = byteswap32(substr($buffer, 28, 4));
  3614.                     substr($buffer, 32, 4) = byteswap32(substr($buffer, 32, 4));
  3615.                     substr($buffer, 36, 4) = byteswap32(substr($buffer, 36, 4));
  3616.                     substr($buffer, 40, 4) = byteswap32(substr($buffer, 40, 4));
  3617.                     substr($buffer, 44, 4) = byteswap32(substr($buffer, 44, 4));
  3618.                     substr($buffer, 48, 4) = byteswap32(substr($buffer, 48, 4));
  3619.                     substr($buffer, 52, 4) = byteswap32(substr($buffer, 52, 4));
  3620.                     substr($buffer, 56, 4) = byteswap32(substr($buffer, 56, 4));
  3621.                     substr($buffer, 60, 8) = byteswap64(substr($buffer, 60, 8));
  3622.                     substr($buffer, 68, 8) = byteswap64(substr($buffer, 68, 8));
  3623.                 }
  3624.                 my $frame_version;
  3625.                 ($frame_version,
  3626.                  $info{'video_type'},
  3627.                  $info{'audio_type'},
  3628.                  $info{'audio_sample_rate'},
  3629.                  $info{'audio_bits_per_sample'},
  3630.                  $info{'audio_channels'},
  3631.                  $info{'audio_compression_ratio'},
  3632.                  $info{'audio_quality'},
  3633.                  $info{'rtjpeg_quality'},
  3634.                  $info{'rtjpeg_luma_filter'},
  3635.                  $info{'rtjpeg_chroma_filter'},
  3636.                  $info{'lavc_bitrate'},
  3637.                  $info{'lavc_qmin'},
  3638.                  $info{'lavc_qmax'},
  3639.                  $info{'lavc_maxqdiff'},
  3640.                  $info{'seektable_offset'},
  3641.                  $info{'keyframeadjust_offset'}
  3642.                  ) = unpack('ia4a4iiiiiiiiiiiill', $buffer);
  3643.             # Found the audio data we want - time to leave
  3644.                  last;
  3645.             }
  3646.         # Done reading frames - let's leave
  3647.             else {
  3648.                 last;
  3649.             }
  3650.         }
  3651.     # Close the file
  3652.         close DATA;
  3653.     # Make sure some things are actually numbers
  3654.         $info{'width'}  += 0;
  3655.         $info{'height'} += 0;
  3656.     # HD fix
  3657.         if ($info{'height'} == 1080) {
  3658.             $info{'height'} = 1088;
  3659.         }
  3660.     # Make some corrections for myth bugs
  3661.         $info{'audio_sample_rate'} = 44100 if ($info{'audio_sample_rate'} == 42501 || $info{'audio_sample_rate'} =~ /^44\d\d\d$/);
  3662.     # NEIL Don't know why he hard set it?
  3663.     #    $info{'aspect'} = '4:3';
  3664.     # Cleanup
  3665.         $info{'aspect'}   = aspect_str($info{'aspect'});
  3666.         $info{'aspect_f'} = aspect_float($info{'aspect'});
  3667.     # Return
  3668.         return %info;
  3669.     }
  3670.  
  3671.     sub aspect_str {
  3672.         my $aspect = shift;
  3673.     # Already in ratio format
  3674.         return $aspect if ($aspect =~ /^\d+:\d+$/);
  3675.     # European decimals...
  3676.         $aspect =~ s/\,/\./;
  3677.     # Parse out decimal formats
  3678.         if ($aspect == 1)          { return '1:1';    }
  3679.         elsif ($aspect =~ m/^1.3/) { return '4:3';    }
  3680.         elsif ($aspect =~ m/^1.7/) { return '16:9';   }
  3681.         elsif ($aspect == 2.21)    { return '2.21:1'; }
  3682.     # Unknown aspect
  3683.         print STDERR "Unknown aspect ratio:  $aspect\n";
  3684.         return $aspect.':1';
  3685.     }
  3686.  
  3687.     sub aspect_float {
  3688.         my $aspect = shift;
  3689.     # European decimals...
  3690.         $aspect =~ s/\,/\./;
  3691.     # In ratio format -- do the math
  3692.         if ($aspect =~ /^\d+:\d+$/) {
  3693.             my ($w, $h) = split /:/, $aspect;
  3694.             return $w / $h;
  3695.         }
  3696.     # Parse out decimal formats
  3697.         if ($aspect eq '1')        { return  1;     }
  3698.         elsif ($aspect =~ m/^1.3/) { return  4 / 3; }
  3699.         elsif ($aspect =~ m/^1.7/) { return 16 / 9; }
  3700.     # Unknown aspect
  3701.         return $aspect;
  3702.     }
  3703.  
  3704. my %info = nuv_info($ENV{'NUVINFOFILE'});
  3705. my $c = 0;
  3706. foreach my $key (split(' ', $ENV{'NUVINFOPROPS'})) {
  3707.     ($info{$key}) or $info{$key} = "NA";
  3708.     ($c++ < 1) and print "$info{$key}" or print ":$info{$key}";
  3709. }
  3710. print "\n";
  3711. #ENDNUVINFO
  3712.  
  3713. ###########################################################################################################
  3714. License Notes:
  3715. --------------
  3716.  
  3717. This software product is licensed under the GNU General Public License
  3718. (GPL). This license gives you the freedom to use this product and have
  3719. access to the source code. You can modify this product as you see fit
  3720. and even use parts in your own software. If you choose to do so, you
  3721. also choose to accept that a modified product or software that use any
  3722. code from mythnuv2mkv.sh MUST also be licensed under the GNU General Public
  3723. License.
  3724.  
  3725. In plain words, you can NOT sell or distribute mythnuv2mkv.sh, a modified
  3726. version or any software product based on any parts of mythnuv2mkv.sh as a
  3727. closed source product. Likewise you cannot re-license this product and
  3728. derivates under another license other than GNU GPL.
  3729.  
  3730. See also the article, "Free Software Matters: Enforcing the GPL" by
  3731. Eben Moglen. http://emoglen.law.columbia.edu/publications/lu-13.html
  3732. ###########################################################################################################