# Media Capture

Figure 1: Initial screen from Palm's Sample Capture app

The Media Capture functionality for recording audio and video and taking camera stills is now part of the Mojo Foundation libraries - there is no longer any need to include "media.js". Instead, your app needs to allocate a Media Capture object and use its APIs, properties and events.

In this section:

- Using Media Capture Functionality in Your Code
- Media Capture API
  - load
  - startAudioCapture
  - startImageCapture
  - startVideoCapture
  - stopAudioCapture
  - stopVideoCapture
  - unload
- Media Capture Interface
  - Attributes
  - Data Structures
  - Events

## Using Media Capture Functionality in Your Code

NOTE: These steps are approximate. They are going to vary in specific ways according to your app's needs.

To include the Media Capture code in your app:

1. If it exists, remove the script tag that includes "media.js".

2. Have the following script tags in your app's index.html file:

       <script src="/usr/palm/frameworks/mojo/mojo.js" type="text/javascript" x-mojo-version="1"></script>
       <script src="/usr/palm/frameworks/mojoloader.js"></script>

3. Load the media extension libraries for media capture in your scene's JavaScript:

       var libraries = MojoLoader.require({ name: "mediacapture", version: "1.0" });

4. Instantiate the Media Capture object:

       this.mediaCaptureObj = libraries.mediacapture.MediaCapture();

   For video capture, allocate the Media Capture object with a video URI to indicate the video element or pipeline that will display the video for preview:

       this.videoObject = this.controller.get('video-object');
       this.mediaCaptureObj = ibraries.mediacapture.MediaCapture(this.videoObject);

5. Select your device format based on your app's criteria.

   Still capture app example:

       var fmt;
       for (i=0; this.mediaCaptureObj.supportedImageFormats.length != i; ++i){
            fmt = this.mediaCaptureObj.supportedImageFormats[i];
            if (fmt.mimetype == "image/jpeg"){
               break;
             }
       }

   Voice recording app example:

       var fmt;
       for (i=0; this.mediaCaptureObj.supportedAudioFormats.length != i; ++i){
            fmt = this.mediaCaptureObj.supportedAudioFormats[i];
            if (fmt.samplerate == 8000){
               break;
             }
       }

6. Select your device for capture.

   Still capture app example:

       var dev;
       for (var i=0; i != this.mediaCaptureObj.captureDevices.length; ++i){
          dev = this.mediaCaptureObj.captureDevices[i];
          for (var typeIdx = 0; typeIdx != dev.inputtype.length; ++typeIdx){
             if (dev.inputtype[typeIdx] == this.mediaCaptureObj.INPUT_TYPE_IMAGE){
                break;
             }
          }
       }

   Voice recording app example:

       var dev;
       for (var i=0; i != this.mediaCaptureObj.captureDevices.length; ++i){
          dev = this.mediaCaptureObj.captureDevices[i];
          for (var typeIdx = 0; typeIdx != dev.inputtype.length; ++typeIdx){
             if (dev.inputtype[typeIdx] == this.mediaCaptureObj.INPUT_TYPE_AUDIO){
                break;
             }
          }
       }

7. Load your capture device. For example - for image:

       this.mediaCaptureObj.load( dev.deviceUri, {"imageCaptureFormat":fmt});

8. Have your event handler in place for capture completion. For example:

       this.mediaCaptureObj.addEventListener("imagecapturecomplete", this.pictureTaken , false);

9. Start media capture. For example - image capture:

       var ImageCaptureOptions ={'quality' : 100,'flash':this.flashValue,'reviewDuration':5,'exifData':{}}
       var picDate = new Date();
       this.picName = "Sample" + picDate.UTC()
       this.mediaCaptureObj.startImageCapture('/media/internal/dts/samples/'+this.picName+'.jpg', ImageCaptureOptions);

10. Clean up when done.

        this.mediaCaptureObj.removeEventListener("imagecapturecomplete",this.pictureTaken , false);
        this.mediaCaptureObj.unload();

## Media Capture API

- load
- startAudioCapture
- startImageCapture
- startVideoCapture
- stopAudioCapture
- stopVideoCapture
- unload

### Note About File Storage

You can save capture files to any location under `/media/internal/`. If your file path does not exist, it is created, including new folders.

## load

Load input device for capture. Starts the capture pipeline, and specifies the capture device. Must be called before capture starts. After your app calls this API, it must call unload before calling it again. Otherwise, the next time your app calls this method, it fails silently.

### Syntax

    void load(string deviceUri, LoadOptions options);

### Parameters

Element | Required | Type | Description
--- | --- | --- | ---
deviceUri | Yes | string | URI of the capture device, read from one of the device selected formats.
options | Yes | LoadOptions | Load options—capture device and capture format.

Example

    load( { "audio",
             {"audioCaptureFormat": {"mimetype":"audio/3gpp","codecs":"samr","bitrate":8000,"samplerate":8000}
           });

## startAudioCapture

Starts an audio capture with the device specified with load. Generates an audiocapturecomplete event when done.

### Syntax

    void startAudioCapture(string path, AudioCaptureOptions options);

### Parameters

Element | Required | Type | Description
--- | --- | --- | ---
path | Yes | string | Path and filename of audio on the device. For example: "/media/internal/audio/sample1.wav"
options | Yes | AudioCaptureOptions | Audio capture options—duration or size.

Example

    startAudioCapture('/media/internal/myaudio/samples/sample' + this.fileExtension, {});

## startImageCapture

Starts an image capture with the device specified with load. Generates an imagecapturecomplete event when done.

### Syntax

    void startImageCapture(string path, ImageCaptureOptions options);

### Parameters

Element | Required | Type | Description
--- | --- | --- | ---
path | Yes | string | Path and filename of image on the device. For example: "/media/internal/pics/sample1.jpg"
options | Yes | ImageCaptureOptions | Image capture options—flash, image quality, Exif metadata, and so on.

Example

    var ImageCaptureOptions ={'quality' : 100,'flash': 2,'reviewDuration':5,'exifData':{}}
    var picDate = new Date();
    this.picName = "Sample" + picDate.UTC();
    this.startImageCapture('/media/internal/dts/samples/'+this.picName+'.jpg', ImageCaptureOptions);

## startVideoCapture

Starts a video capture with the device specified with load. Generates a videocapturecomplete event when done.

### Syntax

    void startVideoCapture(string path, VideoCaptureOptions options);

### Parameters

Element | Required | Type | Description
--- | --- | --- | ---
path | Yes | string | Path and filename of image on the device. For example: "/media/internal/video/sample1.mp4"
options | Yes | VideoCaptureOptions | Video capture options — duration or size and title.

Example

    this.startVideoCapture('/media/internal/video/samples/'+this.vidName+'.mp4',{'title':'Ocean Beach'});

## stopAudioCapture

### Syntax

    void stopAudioCapture();

### Parameters

None

## stopVideoCapture

### Syntax

    void stopAudioCapture();

### Parameters

None

## unload

The capture pipeline is stopped and the capture resources are released.

### Syntax

    void unload();

### Parameters

None

## Media Capture Interface

For instructions on how to use this data structure in your code, see Using Media Capture Functionality in Your Code.

In this section:

- Attributes
- Data Structures
- Events

### Read-only Attributes

Attribute | Type | Description
--- | --- | ---
audioCapture | boolean | Is audio capture active flag.
captureDevices | CaptureDevice array | Available capture devices. Example:
    [{"inputtype":[1],"deviceUri":"audio:","description":"Front Microphone"},
    {"inputtype":[2,3],"deviceUri":"video:","description":"Camera/Camcorder"}]
currentAudioCaptureOptions | AudioCaptureOptions | Current audio capture options.
currentAudioCapturePath | string | Current audio capture path.
currentDeviceUri | string | The input device selected.
currentImageCaptureOptions | ImageCaptureOptions | Current image capture options.
currentImageCapturePath | string | Current image capture path.
currentVideoCaptureOptions | VideoCaptureOptions | Current video capture options.
currentVideoCapturePath | string | Current video capture path.
duration | float | Duration of the currently active capture in seconds. This is set based on the value provided in the capture options. If available space is less than that requested, the duration property is updated and a durationchange event is generated.
elapsedTime | float | Amount of video captured in seconds.
error | int | Indicates operation failure reason. When an error occurs, the error event also fires. Possible values:
    0 - ERROR_NONE,
    1 - ERROR_BAD_SOURCE, (Not currently used)
    2 - ERROR_BAD_MODE, (If capture device is different from loaded device)
    3 - ERROR_NO_SPACE, (No device storage space)
    4 - ERROR_NO_PIPELINE,
    5 - ERROR_RESOURCE_CONFLICT, (For example, some other app is using camera)
    6 - ERROR_TIMEOUT, (General system error)
    7 - ERROR_OTHER
imageCapture | boolean | Flag indicating image (still) capture is active. When `true` (capture starts) the imagecapturestart event is fired.
lastAudioPath | string | Location of the last captured audio.
lastImagePath | string | Location of the last captured image. The path is set before the imagecapturecomplete event fires.
lastVideoPath | string | Location of the last captured video.
ready | boolean | Pipeline state. Transitions to `true` after load (of the capture device) is called.
supportedAudioFormats | CaptureFormat array | Supported audio formats. For example:
    [{"mimetype":"audio/vnd.wave","codecs":"1","bitrate":128000,"samplerate":8000},
    {"mimetype":"audio/vnd.wave","codecs":"1","bitrate":256000,"samplerate":16000},
    {"mimetype":"audio/vnd.wave","codecs":"1","bitrate":7100000,"samplerate":44100},
    {"mimetype":"audio/3gpp","codecs":"samr","bitrate":8000,"samplerate":8000}]
supportedImageFormats | CaptureFormat array | Supported image formats. For example:
    [{"mimetype":"image/jpeg","codecs":"jpeg","width":2032,"height":1520}]
supportedVideoFormats | CaptureFormat array | Supported video formats. For example:
    [{"mimetype":"video/mp4","codecs":"mp4v.20,mp4a.40","width":640,"height":480,"bitrate":1100000}]
videoCapture | boolean | Flag indicating that video capture is active.
vuData | AudioVolume array. | Recent audio samples.

### Data Structures

Structure | Description | Ref'd by | APIs
--- | --- | --- | ---
AudioCaptureOptions | Options for audio capture. |  | startAudioCapture
AudioVolume | Audio volume sample. |  |
CaptureDevice | Description and URI of capture device. |  |
CaptureFormat | Capture format options. | LoadOptions supportedAudioFormats supportedImageFormats supportedVideoFormats | startAudioCapture
ImageCaptureOptions | Options for image capture. |  | startImageCapture
LoadOptions | Load options. |  | load
VideoCaptureOptions | Options for video capture. |  | startVideoCapture

#### AudioCaptureOptions

Options for audio capture.

##### Schema

    {
       duration : float,
       size     : unsigned long
    }

##### Elements

Element | Required | Type | Description
--- | --- | --- | ---
duration | No | float | If specified, capture must stop after this number of seconds. If there is insufficient device storage, the duration is reduced and a `durationchange` event fires.
size | No | unsigned long | As an alternative to `duration`, the maximum size (in bytes) can be specified.

Example

    {
       'size' : 1000000,
    }

#### AudioVolume

Volume information used in vuData property. The structure contains a limited number of recent samples, at a rate of approximately one hundred millisecond. The volume samples are an array based on the number of channels (e.g., [0] (left), [1] (right), ...). Volume samples are normalized to 0~1 (`peak` and `rms`).

##### Schema

    {
        peak : float array,
        rms  : float array,
        time : float
    }

##### Elements

Element | Required | Type | Description
--- | --- | --- | ---
peak | No | float array | The maximum amplitude.
rms | No | float array | RMS (root mean square) — Rates the average, continuous amplifier power output.
time | No | float | Length of time, in seconds, for this sample.

#### CaptureDevice

Description of device for media capture.

##### Schema

    {
       description : string,
       inputtype   : array of InputType,
       deviceUri   : string
    }

##### Elements

Element | Required | Type | Description
--- | --- | --- | ---
description | No | string | Capture device description.
inputtype | No | array of numbers | Input types. Possible values:
    1 - INPUT_TYPE_AUDIO,
    2 - INPUT_TYPE_IMAGE,
    3 - INPUT_TYPE_VIDEO
deviceUri | No | string | Identifier used when calling to load to set the source to this capture device.

Example

    {
       'description' : "Front Microphone",
       "inputtype"   : [1],
       "deviceUri"   : "audio"
    }

#### CaptureFormat

Object returned to the application when reading the supportedXxxFormats attributes.

##### Schema

    {
       bitrate    : unsigned long,
       samplerate : unsigned long,
       height     : unsigned long,
       weight     : unsigned long,
       mimetype   : string,
       codecs     : string
    }

##### Elements

Element | Required | Type | Description
--- | --- | --- | ---
bitrate | No | unsigned long | Estimate for the stream's average total bitrate. Despite being an estimate, it can be used to determine which capture format is most appropriate for the application's needs, e.g., a video streaming app may prefer a capture format whose estimated average bitrate is below 128kb/s.
samplerate | No | unsigned long | Sampling rate for audio.
height | No | unsigned long | For still and video capture modes — the height of the captured image.
width | No | unsigned long | For still and video capture modes — the width of the captured image.
mimetype | No | string | The created file's mimetype.
codecs | No | string | Capture encoding format, which should be chosen based on application requirements. For example, a barcode scanning app could prefer a low compression, or raw codec. This parameter is formatted according to RFC4281 for ISO box files (MP4) and RFC2361 for RIFF files (WAV or AVI).

Example device audio formats

    [{"mimetype":"audio/vnd.wave","codecs":"1","bitrate":128000,"samplerate":8000},
    {"mimetype":"audio/vnd.wave","codecs":"1","bitrate":256000,"samplerate":16000},
    {"mimetype":"audio/vnd.wave","codecs":"1","bitrate":7100000,"samplerate":44100},
    {"mimetype":"audio/3gpp","codecs":"samr","bitrate":8000,"samplerate":8000}]

Example device image formats

    [{"mimetype":"image/jpeg","codecs":"jpeg","width":2032,"height":1520}]

Example device video formats

    [{"mimetype":"video/mp4","codecs":"mp4v.20,mp4a.40","width":640,"height":480,"bitrate":1100000}]

#### ImageCaptureOptions

Options for image capture.

##### Schema

    {
       quality        : unsigned short,
       flash          : int,
       reviewDuration : float,
       exifData       : string
    }

##### Elements

Element | Required | Type | Description
--- | --- | --- | ---
quality | Yes | unisgned short | JPEG quality settings, 0-100. Default is 90.
flash | No | integer | 0 (flash off), 1 (flash auto) or 2 (flash on). Default is 1 (auto).
reviewDuration | No | float | How long, in seconds, the image is displayed after the picture is taken.
exifData | No | string | Exif (Exchangeable image file format) tags to be stored with image. JSON formatted string. Tags supported include "Make", "Model", "CaptureTime" and a GPS structure with fields for Longitude, LongitudeRef, Latitude and LatitiudeRef.

Example

    {
       'duration'       : 100,
       'flash'          : 2,
       'reviewDuration' : 5,
       'exifData'       : {}
    }

#### LoadOptions

Options for load. The CaptureFormat options are for the pipeline. If the pipeline supports multiple options, e.g., concurrent still and video (INPUT_TYPE_IMAGE, INPUT_TYPE_VIDEO), then one option for image, audio and video can be provided.

##### Schema

    {
       imageCaptureFormat : CaptureFormat object,
       audioCaptureFormat : CaptureFormat object,
       VideoCaptureFormat : CaptureFormat object
    }

##### Elements

Element | Required | Type | Description
--- | --- | --- | ---
imageCaptureFormat | No | CaptureFormat object. | Image capture format options.
audioCaptureFormat | No | CaptureFormat object. | Audio capture format options.
VideoCaptureFormat | No | CaptureFormat object. | Video capture format options.

Example

    {
       "format":
                {  "mimetype"   : "audio/3gpp",
                   "codecs"     : "samr",
                   "bitrate"    : 8000,
                   "samplerate" : 8000}
    }

#### VideoCaptureOptions

Options for video capture.

##### Schema

    {
       duration  : float,
       size      : unsigned long,
       title     : string
    }

##### Elements

Element | Required | Type | Description
--- | --- | --- | ---
duration | No | float | If specified, capture stops after this time (in seconds). If there is insufficient device storage, the duration is reduced and a `durationchange`. event fires.
size | No | unsigned long | As an alternative to '`duration`', the maximum size (in bytes) can be specified.
title | No | string | Title to set in the video metadata.

Example

    {
       "duration"       : 100,
       "size"           : 2000000,
       "title"          : "Ocean Beach"
    }

### Events

Event | Description | Audio/Video/Image
--- | --- | ---
audiocapturecomplete | Fired when capture completes. Fires on transition: {lastAudioPath != null}. | A
audiocapturestart | Fired when capture starts. Allows the application to put up UI indicating that capture is in progress. Fires on transition: {audioCapture==true}. | A
durationchange | Fires for all duration changes. | A/V
error | Error event indicates failure starting capture or during capture. fires on transition: {error != ERROR_NONE} | A/V/I
imagecapturecomplete | Fired when capture completes. Fires on transition: {lastImagePath != null} | I
imagecapturestart | Fired when capture starts. Allows the application to put up UI indicating that capture is in progress. Fires on transition: {imageCapture == true}. | I
ready | Fired when the pipeline is successfully loaded and ready to start record. Fires on ready transitions. | A/V/I
videocapturecomplete | Fired when capture completes. Fires on transition: {lastVideoPath != null}. | V
videocapturestart | Fired when capture starts. Allows the application to put up UI indicating that capture is in progress. Fires on transition: {videoCapture == true} | V