# Playing a 3GP file

To play a 3GP file, use the Natural Access ADI service in combination with MMFI functions. Complete the following steps to play a 3GP file:

Step | Action | Use
1 | Check the library version to ensure that it supports the 3GP format. | mmGetVersion
2 | Open the 3GP file. | mmOpenFile in read mode
3 | Obtain information about the 3GP file, including general file information, stream characteristics, and codec configuration. | mmGetFileInfo
4 | For each type of media stream, create the media stream structure, and specify the following information: The stream ID (recommended) A format of NMS packetized (or raw format for an audio stream) Codec information (if you do not specify the stream ID) RTP header settings Whether hint tracks will be used for play processing. | mmOpenStream
5 | Read the next memory buffer from the 3GP file. | mmReadStream
6 | Issue an ADI request to play the data. You can issue one play request for each stream type. If the application is using partial buffer mode (adiPlayMMAsync), repeat the mmReadStream call. | adiPlayMMFromMemory adiPlayMMAsync
7 | When the transmission of all streams is complete, close the 3GP file. | mmCloseFile

## Single buffer play call flow

The call flow for a single buffer play is shown below:

MMFI Lib | App | ADI service
mmGetVersion |
mmOpenFile (write) |
mmGetFileInfo |
mmOpenStream (audio) |
mmOpenStream (video) |
mmReadStream (audio) |
mmReadStream (video) |
| adiPlayMMFromMemory (audio)
| adiPlayMMFromMemory (video)
| ADIEVN_PLAY_DONE (audio)
| ADIEVN_PLAY_DONE (video)
mmCloseFile (write) |

## Partial buffer play call flow

The call flow for a partial buffer play is shown below:

MMFI Lib | App | ADI service
mmGetVersion |
mmOpenFile (read) |
mmGetFileInfo |
mmOpenStream (audio) |
mmOpenStream (video) |
mmReadStream (audio) |
mmReadStream (video) |
| adiPlayMMAsync
| ADIEVN_PLAY_BUFFER_REQ
mmReadStream |
| adiSubmitPlayBuffer
| ADIEVN_PLAY_BUFFER_REQ
mmReadStream |
| adiSubmitPlayBuffer
| ADIEVN_PLAY_DONE
mmCloseFile (write) |

## Random access call flow

To randomly access and play a 3GP file, use the Natural Access ADI service in combination with MMFI functions as explained in the examples in this section.

### Restrictions on ADI Processing and random access

There are restrictions on ADI processing when performing seek operations for random access. The restrictions are:

- During a playback, seek operations (mmSeekToTime, mmSeekToNextSyncPoint, mmSeekToPrevSyncPoint) may not be performed while ADI play (adiPlayMMAsync) is in progress.

- A seek operation may only be performed when playing back using partial buffer mode (adiPlayMMAsync).

- Only mmSeekToTime and mmSeekToNextSyncPoint seek operations are allowed before the first ADI play function.

- When a seek operation is called after the first ADI play, the following steps must be performed:

Step | Action
1 | Stop ADI processing using adiStopPlaying.
2 | Perform the seek operation using mmSeekToTime, mmSeekToNextSyncPoint, or mmSeekToPrevPoint.
3 | Start the play process as before using mmReadStream and adiStartPlaying.

### Example 1: Seeking before the first ADI play

The following table shows a call flow for using random access functions after the first ADI play function call.

Step | Action | Use
1 | Check the library version to ensure that it supports the 3GP format. | mmGetVersion
2 | Open the 3GP file. | mmOpenFile in read mode
3 | The returned structure FILE_INFO_DESC contains a field named NbSyncPoints. This provides the size of the sync table for future use in the application. | mmGetFileInfo
4 | Open the media stream. | mmOpenStream
5 | Allocate memory for the time-based sync table according to the field NbSyncPoints. The memory allocation is for an array of unsigned integers with size equal to NbSyncPoints. |
6 | Obtain the time-based sync table. The timing information is in milliseconds. | mmGetSyncPoints
7 | Using the obtained sync point information, set the track position pointer to a time within the 3GP file, or move the track position pointer to the next sync point. | mmSeekToTime mmSeekToNextSyncPoint
8 | Read the next memory buffer from the 3GP file. | mmReadStream
9 | Play the next buffer. | adiPlayMMAsync
10 | When the transmission of all streams is complete, close the 3GP file. | mmCloseFile

A call flow using random access functions in this manner is shown below:

MMFI Lib | App | ADI service
mmGetVersion |
mmOpenFile (read) |
mmGetFileInfo |
mmOpenStream (audio) |
mmOpenStream (video) |
mmGetSyncPoints(file) |
mmGetCurrentTime(file) |
mmSeektoTime(file) mmSeektoNextSyncPoint(file) |
mmReadStream (audio) |
mmReadStream (video) |
| adiPlayMMAsync
| ADIEVN_PLAY_BUFFER_REQ
mmReadStream |
| adiSubmitPlayBuffer
| ADIEVN_PLAY_BUFFER_REQ
mmReadStream |
| adiSubmitPlayBuffer
| ADIEVN_PLAY_DONE
mmCloseFile (write) |

### Example 2: Seeking after the first ADI play

The following table shows a call flow for using random access functions after the first ADI play function call.

Step | Action | Use
1 | Check the library version to ensure that it supports the 3GP format. | mmGetVersion
2 | Open the 3GP file. | mmOpenFile in read mode
3 | The returned structure FILE_INFO_DESC contains a field named NbSyncPoints. This provides the size of the sync table for future use in the application. | mmGetFileInfo
4 | Open the media stream. | mmOpenStream
5 | Allocate memory for the time-based sync table according to the field NbSyncPoints. The memory allocation is for an array of unsigned integers with size equal to NbSyncPoints. |
6 | Obtain the time-based sync table. The timing information is in units of ms. | mmGetSyncPoints
7 | Read the next memory buffer from the 3GP file. | mmReadStream
8 | Play the next buffer. ADI play and mmReadStream operations continue until the seek operation is performed. | adiPlayMMAsync adiSubmitPlayBuffer
9 | Stop ADI processing before the seek operation. | adiStopPlaying
10 | Obtain the track position pointer's current value if needed by the application. | mmGetCurrentTime
11 | Using the obtained sync point information, set the track position pointer to a time within the 3GP file, or move the track position pointer to the next or previous sync point. | mmSeekToTime mmSeekToNextSyncPoint mmSeekToPrevSyncPoint
12 | Read the next memory buffer from the 3GP file (as in Step 7). | mmReadStream
13 | Play the buffer. | adiPlayMMAsync adiSubmitPlayBuffer
14 | When the transmission of all streams is complete, close the 3GP file. | mmCloseFile

The following illustration shows a call flow performing random access on a 3GP file after the first ADI play function call:

Part 1

MMFI Lib | App | ADI service
mmGetVersion |
mmOpenFile (read) |
mmGetFileInfo |
mmOpenStream (audio) |
mmOpenStream (video) |
mmGetSyncPoints(file) |
mmReadStream (audio) |
mmReadStream (video) |
| adiPlayMMAsync
| ADIEVN_PLAY_BUFFER_REQ
mmReadStream |
| adiSubmitPlayBuffer
| ADIEVN_PLAY_BUFFER_REQ
| ...
| adiStopPlaying
| ADIEVN_PLAY_DONE

Part 2

MMFI Lib | App | ADI service
mmGetCurrentTime(file) |
mmSeekToTime(file) mmSeekToNextSyncPoint(file) mmSeekToPrevSyncPoint(file) |
mmReadStream(audio) |
mmReadStream(video) |
| adiPlayMMAsync
| ADIEVN_PLAY_BUFFER_REQ
| adiSubmitPlayBuffer
| ADIEVN_PLAY_DONE
| ...
mmCloseFile (write) |