August 2013 Archives

YouTube "Playback Error" (iOS)

I was recently afflicted by the dreaded YouTube "Playback Error" on most of the iOS devices in my house, including two iPhones. My nephew's iPad was afflicted, but mine did not appear to be, at least when I initially tested it.

I found a solution, but honestly it's not entirely likely to be the problem anyone else is experiencing. Unless, of course, you're in an organization where the vast majority of your iOS devices are exhibiting this behavior, then keep reading.


It was not specific to the YouTube app, at least on my iPhone 5. If I went to youtube.com in Safari and tried to watch a video, it did not seem to start. The YouTube app failed pretty quickly with "Playback Error" usually, but I've also seen it fail to start playing, with the little waiting circle thingie spinning for what appears to be forever.

YouTube in Safari on my MacBook Air laptop, however, worked fine, and it was using the same Apple Airport Express Wi-Fi access points as the iPhones.

And, to complicate things further, all of the devices worked properly at Mom and Dad's. They use an Apple Airport Express access point and an Apple Airport Extreme that is a Wi-Fi access point, as well as being the firewall, router and DNS.

I tried several of the most popular and what to watch videos listed in the app, and all of them experience this problem. Note that many of these have a pre-roll advertisement, which may or may not be significant. While searching for advice on this problem, this was mentioned in a few postings.

Of course everything has been rebooted at least once. All software was updated to the latest version as of August 31, 2013. iOS 6.1.4, YouTube 2.0.0.7804. AirPort 7.6.4.

My great breakthrough occurred when I finally got a good packet capture of what's going on when a playback error occurs. 192.168.2.200 is my iPhone 5 and I started the capture just before playing one of the recommended videos for the first time, and a playback error occurred almost immediately. Here's a picture of the trace in Wireshark.

playback_error.jpgIf you click on the picture it will open in a larger window which is presumably easier to read.

Anyway, what you can see is that the problem appears to be DNS related, which makes some sense. The iPhone is rejecting some of the DNS responses from my router. YouTube/iOS sends out an unusually large number of concurrent DNS queries, 9, in fact, 4 of which are duplicates. Several of these fail to resolve because iOS stops listening on the receiving port, which causes an ICMP destination unreachable message to be sent back to the DNS server (192.168.2.1).

In my case, I have a Netgear FVS-124 dual WAN router that acts as my border router and firewall. It also served as my DNS server. I've had mysterious hard-to-reproduce problems using this as a DNS server in the past, and, well, for whatever reason, it apparently decided to cause problems again.

I ended up installing a new recursive DNS server inside my firewall on a Linux server and pointed all of the access points to use that as the DNS for DHCP.

Important tip: Even though I changed the DNS sever IP address on the access points, iOS did not recognize the change. It continued to point at the old router-based DNS until I forgot the Wi-Fi network and logged back into it again.

And, wonder of wonders, everything then worked perfectly! Every video played exactly as expected on every device.


Since I really only worked around the problem, I don't exactly know the root cause. But I'll put some blame on YouTube for needing to query so many different host names to play a video, the iOS resolver for not coalescing queries for the same host in rapid succession before a response comes back into one request and some to the Netgear router, which is obviously doing something differently than Linux to confuse iOS, which may or may not be the fault of iOS.

In any case, if a large number of iOS devices in your organization are experiencing "Playback Error" in YouTube, stick a packet analyzer between the devices and your local DNS and see if you're getting a similar packet trace. If so, you're experiencing something similar to what I was seeing and you should look toward something DNS related.

Fun with servo motors!

servo1.jpg
I thought it might be fun to play around with some servo motors. I never really did anything with them before, and they could come in handy for building mechanical things.

My experiment basically has two controls. When you turn the potentiometer, the left servo moves to the corresponding position. When you press or hold the left button, the right servo turns to the left. The center button moves it to the right. Fun stuff!




While the Raspberry Pi has two PWM outputs that could control the servos directly, I got an Adafruit 16-Channel 12-bit PWM/Servo Driver - I2C interface to make it easy to control up to 16. Plus, it has nice header pins that fit standard servo motor connectors.


It just requires a little soldering to mount the headers and a 5VDC power supply to power the servos. Quick and easy.

elec1.jpgAdafruit has a nice tutorial on how to set everything up too. You may need to enable I2C support in Linux, as by default it's off in Raspbian distributions, but it's easy to enable.


I got a couple micro servos and a continuous rotation servo from Adafruit to play with, too.


I knew that they used servo motors in things like RC boats and airplanes to control things like rudder, flaps, etc. but I didn't really know how they worked. This tutorial helped.

The basic idea is that they generally have limited range (say, 180° of rotation), offer relatively precise positioning, and can hold that position (with some limitations).

There are only three wires to a servo motor, however, and two of them are power (5 to 6 VDC and ground). The third wire is used to communicate position.

It uses pulse-width modulation. You need to send the servo a pulse 50-60 times a second to keep or change its position. The width of the high part of the pulse determines the angle. For example, 1 millisecond would be 0°, 1.5 ms. would be 90°, and 2 ms. would be 180°. The rotation amounts vary depending on the servo, but 1 ms. = full left and 2 ms. = full right, whatever that might be.

The reason for this wacky encoding method is that it's easy to time division multiplex these signals very across a single radio frequency link. It allowed early RC planes and such to implement the controls entirely with inexpensive discrete components, without even any microcontrollers!


On the breadboard above the leftmost thing is the PWM driver and the thing next to it, with the big ribbon cable, is the Pi Cobbler, that allows access to the Raspberry Pi I/O pins.


The PWM driver just needs connections to power (3.3V), ground and the SDA and SCL lines on the Pi Cobbler board for the I2C interface. Also, an external 5 VDC power supply, and connections to the servo motors.


The next thing on the breadboard is an MCP3008, 8-channel, 12-bit, SPI interface Analog to Digital Converter (ADC). The Raspberry Pi doesn't include any analog inputs, but it's easy to add them with a MCP3008.

MCP3008.jpgPin 1 CH0 - Connect to the center tap of a potentiometer
Pin 9 DGND - Connect to ground
Pin 10 CS - Connect to Pi Cobbler CE0 (GPIO8)
Pin 11 DIN - Connect to Pi Cobbler MOSI (GPIO10)
Pin 12 DOUT - Connect to Pi Cobbler MISO (GPIO9)
Pin 13 CLK - Connect to Pi Cobbler SCKL (GPIO11)
Pin 14 AGND - Connect to ground
Pin 15 VREF - Connect to 3.3V
Pin 16 VDD - Connect to 3.3V

The newer Raspbian distros include kernel SPI support, but the Adafruit example doesn't use it, and for what I was doing I didn't need high performance, so I just use the Adafruit Python sample code that bit bangs the SPI for the MCP3008.


The next things on the breadboard are LEDs, one red and one green. The red is connected to GPIO22 and green to GPIO23. The short lead on the LED connects to ground via a 330 ohm resistor. The LEDs and resistors are included in the Adafruit Raspberry Pi starter kit. The software included here doesn't use them, however.


There is a 10K linear potentiometer. One side connects to ground, the other to 3.3V, and the center tap connects to the ADC. The MCP3008 is a 12-bit ADC, so it returns values from 0 to 1023 in the software. This particular pot fits nicely in the breadboard.


Lastly, I put 3 microswitches, also included in the Adafruit kit. The Raspberry Pi includes built-in software support for enabling weak pull-up or pull-down resistors on input lines, but as far as I can tell, this is not implemented in the Python library. WiringPi supports it. Anyway, I didn't want to go digging into the Python library code, so I just put 10K pull-down resistors on the switch inputs. I set them up as:

Left GPIO4
Center GPIO24
Right GPIO17

servo2.jpg
That's all the hardware, the rest is all fun in software!


The potentiometer and ADC are linked to one of the servos in software. When you turn the pot to left, the servo moves to the left. To the right, the servo moves to the right. It's pretty cool, and just a few lines of code!

        pot = mcp3008.readadc(POT_ADC_CHAN, SPICLK, SPIMOSI, SPIMISO, SPICS)
        if lastpot != pot:
            # Pot range 0 - 1023, scale to SERVO_MIN to SERVO_MAX
            # Also subtract pot from 1023 otherwise it rotates backward 
            val = (1023 - pot) * (SERVO_MAX - SERVO_MIN) / 1024 + SERVO_MIN
            pwm.setPWM(0, 0, val)
            lastpot = pot


I linked the other servo to the left and center switches. When you hit the left button, it moves left. When you hit the right button it moves right. And you can hold down the button.

        if GPIO.input(LEFT_SW) == 0:
            if servo1 > SERVO_MIN:
                servo1 = servo1 - 1
                pwm.setPWM(1, 0, servo1)

I haven't done anything with the right switch or the LEDs, but that's just a simple matter of software...


Here's the full source (tar/gzip archive, 5K). It's just a bit of test code that I threw together, so it's not cleaned up and prettified. Execute ServoTest.py in Python.


I should point out that I think you could probably make a potentiometer control a servo motor using a 555 timer IC and a few resistors and capacitors (maybe a diode too) to do the PWM. But that is not nearly as fun!

About this Archive

This page is an archive of entries from August 2013 listed from newest to oldest.

July 2013 is the previous archive.

October 2013 is the next archive.

Find recent content on the main index or look in the archives to find all content.

Categories

Pages