From MythTV Official Wiki
Revision as of 23:34, 25 August 2014 by Jpoet (talk | contribs) (External Recorder)

Jump to: navigation, search

External Recorder

As of v0.28-pre-1073-ga9ce4c09b mythbackend has the ability to communicate with an external "Black Box" application for recording. This external application module does whatever it needs to do to generate a transport stream which mythbackend then reads and records.

Using an External Recorder

Run mythtv-setup and choose "External Recorder" for the type of capture card. Fill in the path to the application and include any command line arguments needed. The standard myth arguments will also be passed (e.g. -q --syslog none --logpath -v).

Myth will expect a MPTS from the application, but that does not mean there must be more than one program in the transport stream. If the application reports that it has a 'tuner', then mythbackend will try to use it to tune to an appropriate channel. Depending on the source, you may need to manually enter channels via "6. Channel Editor" in mythtv-setup. If you do add channels, make sure the ServiceID is set to a non-Null value.

Writing an External Recorder

When mythbackend wants to start a recording using the 'External Recorder', it executes the application, and then communicates with it via STDIN, STDOUT and STDERR. Commands will show up on the applications STDIN. The application will respond to the commands via its STDERR. When told to stream a MPTS (or SPTS) the application will send the data out STDOUT.

These are the commands that the external recorder application (module) needs to understand:

  • "Version?" (Valid respons is "OK:" followed by an version information the application wishes to provide.
  • "IsOpen?" (Valid response is "OK:Yes" or "OK:No") Is the recorder application in a good state?
  • "CloseRecorder" (Valid response is "OK:Terminating", and then the application will shut down)
  • "HasTuner?" (Valid response is "OK:Yes" or "OK:No") Does the recorder have a tuner?
  • "HasPictureAttributes?" (Valid response is "OK:Yes" or "OK:No") Does the recorder support picture adjustments (hue, brightness, etc.)?
  • "LockTimeout?" (Valid response is "OK:<value>", where value indicates a value in ms indicating when to give up on acquiring a signal lock)
  • "SignalStrenghtPercent?" (Valid response is "OK:<value>", where value indicates the strength of the signal in a range of 0-100). App should return "OK:100" if the concept of a signal strength does not apply.
  • "HasLock?" (Valid response is "OK:Yes" or "OK:No") If not applicable, app should return "OK:Yes"
  • "FlowControl?" (Valid response is "OK:Polling" or "OK:XON/XOFF").
  • "BlockSize:<value>" (Valid response is OK") This tells the app the maximum number of bytes that can be sent without mythbackend blocking.
  • "StartStreaming" (Valid response is "OK:Started", and the Transport Stream should be sent to STDOUT)
  • "StopStreaming" (Valid response is "OK:Stopped", and data should no longer be sent to STDOUT)
  • "XON" (Valid response is "OK", and the app is allowed to write to STDOUT)
  • "XOFF" (Valid response is "OK", and the app should stop writing to STDOUT)
  • "SendBytes" (Valid response is "OK")

For any response that can just be "OK", the application may send other information after the "OK". For example, a response of "OK:5632423 bytes sent" is a valid response for the "SendBytes" command.

If the application returns "OK:Yes" to "HasTuner?", then it needs to handle:

  • "TuneChannel:<value>"

<value> will be a channel number, possibly looking like 1234-23 to indicate major-minor elements.

If the application returns "OK:Yes" to "HasPictureAttributes?", then it also needs to deal with these commands:

  • "SetBrightness:<value>"
  • "SetContrast:<value>"
  • "SetColour":<value>"
  • "SetHue":<value>”

Note: The PictureAttribute commands are currently unimplemented.

If FlowControl is set to Polling, then the application needs to processes the SendBytes command. If FlowControl is set to XON/XOFF, then the application needs to process XON and XOFF commands. Polling mode works better for applications which generally end up waiting on mythbackend to send data. XON/XOFF works better for applications which are event driving, and spend more time waiting on the recording source.

When the external module receives the "XON", "XOFF" or "SendBytes" command, it will respond in one of four ways via its STDERR:

  • "OK"
  • "OK: some descriptive text" -- same as just "OK", but allows the external module to tell mythbackend to log the external module's 'state'.
  • "WARN: some descriptive text" -- which may indicates that the external module is not able to send any bytes right now, but to try again.
  • "ERR: some descriptive text" -- which indicates that the external module is in an error state, and the recording needs to abort and possibly restart.

This enables a "flow control" between the external module and mythbackend and allows the external module to report problems.

The external module has the burden of buffering the transport stream. If mythbackend does not read the transport stream fast enough from the external module, the external module will have to decide if it needs to increase its buffer, or if it should drop packets. If the external module needs to drop packets, that might be a case where it would respond with something like "OK: # packets have been dropped".

When mythbackend first starts up it will invoke the external application and send it various commands like "Version?". If no errors are detected then that "input" will be put into a "good" stage, and the "CloseRecorder" command will be sent to the app. When LiveTV or a recording is ready to start, the application will be launched again and will be kept active until it is no longer needed.


Bundled with myth is the mythfilerecorder application. It is an "External Recorder" which operates using polling flow control. Configure it in mythtv-setup with a command line like "/usr/local/bin/mythfilerecorder --infile <somefile>". By default it will loop back to the beginning of the file when it reaches the end of the file. It can be given the --noloop argument to disable this behavior.