Saturday, 14 October 2017

Toshiba 32PU200 TV as media player that does not suck

Lame: Toshiba 32PU200
[Updated 2021-02-05]
My eyesight is not getting any better, so some years ago, I started using Full HD (1920x1080 resolution) TVs as desktop monitors. This is not ideal unless you sit further away from the TV. The TV tends to be to big to fit on a desktop(especially if you mounted more than one!) so the 32-inch Toshiba 32PU200 was a reasonable compromise.

It worked well for me for a few years- I now have three screens at each workstation: a monitor, TV and the laptop screen. Two of the TVs in the study failed from lightning strikes. In both cases they damaged the TV's HDMI interface so that the laptop or desktop can no longer send images to the TV.  However, they still worked as TVs, except I no longer watched TV much.

Repair proved difficult: the designed boiled down to just one huge IC(Realtek RTD2668 LCDTV controller), and its replacement involved hand-soldering 128 pins of 0.5mm pitch. This would be a couple or hours work with the microscope. But the TV was supposed to make less work for my eyes.


Realtek LCD TV controller RTD2668
I started using the 32PU200 as a media player in the bedroom. It has a USB port which will accept a thumb drive, except it turned out to be rather lame: it used Microsoft FAT32 file formatting, and worse seemed subject to the usual inexplicable random Microsoft handicaps. It would not play some movies. Some movies caused it to go into a permanent reboot loop. Not to mention the usual random hangups.

Defenestration is not an option. To get around this I used mencoder (mencoder comes with mplayer which is standard issue for Slackware 14.2) to re-encode the problem movies on my laptop before transferring them to the thumbdrive (I use a Sandisk Ultra for high speed). mencoder with pretty much default settings produced immediate results:

mencoder BabyDriver.mkv -o BabyDriver.avi -oac pcm -of avi -ovc lavc

It was so fast, mencoder can be (and often is) used to re-encode and stream movies on the fly. But now and then I get a really good quality movie and the above settings resulted in rather poor blocky colors. For cases like these the re-encoding can take as much as four hours but the results are quite satisfying.

First you need to calculate the bitrate. The formula is

optimal_bitrate = 50 * 25 * width * height / 256

For the 32PU200, width is 1920 and height is 1080, so my best bitrate is 10125000

For best quality we go for a two pass method (you run mencoder twice on the same file). This lets mencoder do really well on the action sequences, explosions, etc.

Now the mencoder command becomes:

mencoder ./BabyDriver.mkv -o ./BabyDriver.avi -oac lavc -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=10125000:v4mv:mbd=2:trell:cmp=3:subcmp=3:autoaspect:vpass=1 -vf hqdn3d=2:1:2

For the second pass the command is mostly the same except we use vpass=2

mencoder ./BabyDriver.mkv -o ./BabyDriver.avi -oac lavc -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=10125000:v4mv:mbd=2:trell:cmp=3:subcmp=3:autoaspect:vpass=2 -vf hqdn3d=2:1:2

Notice the file has ballooned to almost double the size:
-rwxr-xr-x 1 root root 2.3G Oct 15 01:41 BabyDriver.avi

The original being
-rw-r--r-- 1 heong users 1.2G Oct  1 16:14 BabyDriver.mkv

If the original picture has a lower bitrate, say it is originally 640 by 480 resolution, you can reduce the bloat a little by reducing the bitrate:
$echo "50*25*640*480/256" | bc
1500000

The picture for the most part is quite satisfying, and the TV gets a reprieve from the scrap heap for now.

mencoder does not do well with Google's WebM files, so ffmpeg (here are some useful scripts) might work better for you:

ffmpeg -i "BabyDriver.webm" -c:v mpeg4 -c:a mp3 -qscale 0 BabyDriver.mp4

where 'qscale 0' is used to preserve video quality, so adjust for bloat accordingly.

If the video framerate is too high, the 32PU200 might return a 'video framerate not supported' error. The cure is a simple:

ffmpeg -i HighFrameRate.avi -codec copy -bsf:v mpeg4_unpack_bframes -r 50 50fpsFrameRate.avi

The 'mpeg4_unpack_bframes' portion is in case mplayer (not 32PU200) should complain that the avi file:

[mpeg4 @ 0x7fec04102460]Video uses a non-standard and wasteful way to store B-fr
ames ('packed B-frames'). Consider using the mpeg4_unpack_bframes bitstream filt
er without encoding but stream copy to fix it.

It is not crucial and can be left out.

Sometimes we have to re-encode the video and/or audio format into those recognized by the PU300. To find the codec types just take the text output from mplayer:

mplayer test.mkv

Might produce:
==========================================================================
Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family
libavcodec version 58.35.100 (external)
Selected video codec: [ffvp9] vfm: ffmpeg (FFmpeg VP9)
==========================================================================
Clip info:
 ENCODER: Lavf58.20.100
Load subtitles in ./
==========================================================================
Opening audio decoder: [ffmpeg] FFmpeg/libavcodec audio decoders
AUDIO: 44100 Hz, 2 ch, floatle, 0.0 kbit/0.00% (ratio: 0->352800)
Selected audio codec: [ffaac] afm: ffmpeg (FFmpeg AAC (MPEG-2/MPEG-4 Audio))
==========================================================================

The video codec is ffvp9 and the audio is ffaac. To see if how ffmpeg names the codec, just do:

ffmpeg -codecs

The ffmpeg name for the video codec is vp9 and audio is aac. The PU300 can accept aac but not vp9 so the video needs to re-encoded to something it likes, say mpeg4. The video resolution happened to be too high at 3840x1608 and needs to be reduced to 1920x1080, so the final command is

ffmpeg -c:v vp9 -i test.mkv -vf scale=1920:1080 -c:v mpeg4 -c:a copy  -q:v 0 -max_muxing_queue_size 1024 test.mp4

Since the command takes a really long time to finish, it helps to test on a short 20s clip of the original video starting from the 10th second:

ffmpeg -ss 00:10:00 -t 00:00:20 -i FullLengthVideo.mkv -acodec copy -vcodec copy  -avoid_negative_ts 1 test.mkv

Sometimes it is handy (instead of fast-forwarding) to be able to divide the video into 10 chapters and rapidly scan by chapter.

$ffmpeg -c:v mpeg1video -c:a mp2 -i ~/old_video.mpg -i ~/FFMETADATAFILE.txt -map_metadata 0 -map_metadata:s:v 0:s:v -map_metadata:s:a 0:s:a -c:v mpeg4 -c:a mp3 -q:v 0 ~/old_video_indexed.mp4

Where the metadata file is something like:

$cat ~/FFMETADATAFILE.txt                           ;FFMETADATA1
encoder=Lavf58.20.100
[CHAPTER]
TIMEBASE=1/1000
START=1
END=524000

[CHAPTER]
TIMEBASE=1/1000
START=524001
END=1049200

[CHAPTER]
TIMEBASE=1/1000
START=1049201
END=1573800

[CHAPTER]
TIMEBASE=1/1000
START=1573801
END=2098400

[CHAPTER]
TIMEBASE=1/1000
START=2098401
END=2623000

[CHAPTER]
TIMEBASE=1/1000
START=2623001
END=3147600

[CHAPTER]
TIMEBASE=1/1000
START=3147601
END=3672200

[CHAPTER]
TIMEBASE=1/1000
START=3672201
END=4196800

[CHAPTER]
TIMEBASE=1/1000
START=4196801
END=4721400

The duration, video and audio encoding can be listed using:

$ffprobe ~/old_video.mpg
ffprobe version 4.1.4 Copyright (c) 2007-2019 the FFmpeg developers
  built with gcc 9.1.0 (GCC)
  configuration: --prefix=/usr --libdir=/usr/lib64 --shlibdir=/usr/lib64 --docdir=/usr/doc/ffmpeg-4.1.4/html --mandir=/usr/man --disable-debug --enable-shared --disable-static --enable-gpl --enable-version3 --enable-avresample --arch=x86_64 --disable-encoder=aac --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-gnutls --enable-libbluray --enable-libcaca --enable-libcdio --enable-libopus --enable-libspeex --enable-libssh --enable-libtheora --enable-libv4l2 --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libmp3lame --enable-opencl --enable-opengl --enable-libopenjpeg --enable-libpulse --enable-libsmbclient --enable-libwavpack
  libavutil      56. 22.100 / 56. 22.100
  libavcodec     58. 35.100 / 58. 35.100
  libavformat    58. 20.100 / 58. 20.100
  libavdevice    58.  5.100 / 58.  5.100
  libavfilter     7. 40.101 /  7. 40.101
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  3.100 /  5.  3.100
  libswresample   3.  3.100 /  3.  3.100
  libpostproc    55.  3.100 / 55.  3.100
Input #0, mpeg, from 'old_video.mpg':
  Duration: 01:31:36.96, start: 0.533367, bitrate: 1535 kb/s
    Stream #0:0[0x1e0]: Video: mpeg1video, yuv420p(tv), 360x240 [SAR 200:219 DAR 100:73], 1400 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 29.97 tbc
    Stream #0:1[0x1c0]: Audio: mp2, 48000 Hz, stereo, s16p, 128 kb/s

After adding the metadata ffprobe has extra metadata output:

  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    encoder         : Lavf58.20.100
  Duration: 01:31:36.98, start: 0.000000, bitrate: 1326 kb/s
    Chapter #0:0: start 0.001000, end 524.001000
    Metadata:
      title           : 
    Chapter #0:1: start 524.001000, end 1049.201000
    Metadata:
      title           : 
    Chapter #0:2: start 1049.201000, end 1573.801000
    Metadata:
      title           : 
    Chapter #0:3: start 1573.801000, end 2098.401000
    Metadata:
      title           : 
    Chapter #0:4: start 2098.401000, end 2623.001000
    Metadata:
      title           : 
    Chapter #0:5: start 2623.001000, end 3147.601000
    Metadata:
      title           : 
    Chapter #0:6: start 3147.601000, end 3672.201000
    Metadata:
      title           :  from mjpeg to 
    Chapter #0:7: start 3672.201000, end 4196.801000
    Metadata:
      title           : 
    Chapter #0:8: start 4196.801000, end 5496.984000
    Metadata:
      title           : 

How to add audio to a video and convert the video encoding from mjpeg to mpeg4, convert the audio from mp3 to aac:

$ffmpeg -c:v mjpeg -i videofile.avi -c:a mp3 -i audiofile.mp4 -c:v mpeg4 -c:a aac -map 0:v -map 1:a -q:v 0 video-audio.mp4



Happy trails.

2 comments: