Skip Headers

Oracle® interMedia Annotator User's Guide
Release 9.2
Part No. A96120-01
Go To Documentation Library
Home
Go To Product List
Book List
Go To Table Of Contents
Contents
Go To Index
Index

Master Index

Feedback

Previous Next

6
Custom Parser Example

This chapter provides an example of creating a new parser for a custom content format. It describes AuParser, which is an example of a user-developed parser for a custom content format that was written using the Oracle interMedia Annotator parser API. This example contains user-defined methods that use Java and interMedia Annotator APIs to define a parser for the NeXT/Sun AU file format. The purpose of the parser is to extract the format encoding information and the associated user data from the file.

The source code is contained in the file AuParser.java, which is included in the parsers.zip file at the following location:

The example shown in this chapter will not necessarily match the code shipped as AuParser.java with the Oracle interMedia Annotator installation. If you want to run this example on your system, use the file provided with the installation; do not attempt to compile and run the code presented in this chapter.


Note:

This chapter contains examples of Java code. Some of the code examples display numbers enclosed in brackets; these indicate that further explanation of that code is in the numbered list immediately following the example.

6.1 Parser Creation Overview

To define a new parser, perform the following operations:

  1. Create a new Java class that inherits properties and methods from the class oracle.ord.media.annotator.parsers.Parser. In this example, the Java class is called AuParser and is defined in the AuParser.java file.

    The new Java class must implement the following methods:

    • parse( ): Parses the content from the InputStream object.

    • saveToAnnotation( ): Saves the results of the parsing as an annotation named m_annInst.

    • extractSamples( ): Extracts samples from the media source file. You must implement this method whether or not you want to support sample extraction.

    Additionally, you can add other methods depending on the operations that you want the parser to perform.

    Section 6.3 through Section 6.10 describe the contents of the AuParser.java example.

  2. Write a parser descriptor XML file and add it to the following directory:

    • On UNIX:

      $ORACLE_HOME/ord/Annotator/lib/descriptors/parsers

    • On Windows:

      ORACLE_HOME\ord\Annotator\lib\descriptors\parsers

    This directory also contains an example of a parser descriptor XML file, AuParser.xml.

  3. Optionally, modify the Annotator.mime file to set your parser to be used for a specific MIME type. This file is located in the following directory:

    • On UNIX: $ORACLE_HOME/ord/Annotator/lib/conf

    • On Windows: ORACLE_HOME\ord\Annotator\lib\conf

6.2 AU File Structure

Example 6-1 shows the basic structure of an AU formatted file.

Example 6-1 Basic Structure of an AU File

typedef struct {

     int magic;               // magic number SND_MAGIC

     int dataLocation;        // offset or pointer to the data

     int dataSize;            // number of bytes of data

     int dataFormat;          // the data format code

     int samplingRate;        // the sampling rate

     int channelCount;        // the number of channels

     char info[4];            // optional text information

} SNDSoundStruct;

The parameter magic must be equal to SND_MAGIC ((int)0x2e736e64), which is a representation of the ASCII characters ".snd". The parameter info will be associated with the user data attribute of the annotation.

6.3 Package and Import Statements

Example 6-2 shows the import statements that must be included in the Java program to properly run an interMedia Annotator parser, and the package statements that set the package of this class.

Example 6-2 Package and Import Statements

package oracle.ord.media.annotator.parsers.au;


import java.io.*;

import java.util.*;

import java.net.*;


import oracle.ord.media.annotator.parsers.*;

import oracle.ord.media.annotator.annotations.*;

import oracle.ord.media.annotator.utils.*;

6.4 Class Definition and Instance Variables

Example 6-3 shows the class definition and instance variables for the AuParser class.

Example 6-3 Class Definition and Instance Variables

public class AuParser extends Parser{

     private static final Integer SND_FORMAT_UNSPECIFIED = new Integer(0);

     private static final Integer SND_FORMAT_MULAW_8 = new Integer(1);

     private static final Integer SND_FORMAT_LINEAR_8 = new Integer(2);

     private static final Integer SND_FORMAT_LINEAR_16 = new Integer(3);

     private static final Integer SND_FORMAT_LINEAR_24 = new Integer(4);

     private static final Integer SND_FORMAT_LINEAR_32 = new Integer(5);

     private static final Integer SND_FORMAT_FLOAT = new Integer(6);

     private static final Integer SND_FORMAT_DOUBLE = new Integer(7);

     private static final Integer SND_FORMAT_INDIRECT = new Integer(8);

     private static final Integer SND_FORMAT_NESTED = new Integer(9);

     private static final Integer SND_FORMAT_DSP_CORE = new Integer(10);

     private static final Integer SND_FORMAT_DSP_DATA_8 = new Integer(11);

     private static final Integer SND_FORMAT_DSP_DATA_16 = new Integer(12);

     private static final Integer SND_FORMAT_DSP_DATA_24 = new Integer(13);

     private static final Integer SND_FORMAT_DSP_DATA_32 = new Integer(14);

     private static final Integer SND_FORMAT_UNKNOWN = new Integer(15);

     private static final Integer SND_FORMAT_DISPLAY = new Integer(16);

     private static final Integer SND_FORMAT_MULAW_SQUELCH = new Integer(17);

     private static final Integer SND_FORMAT_EMPHASIZED = new Integer(18);

     private static final Integer SND_FORMAT_COMPRESSED = new Integer(19);

     private static final Integer SND_FORMAT_COMPRESSED_EMPHASIZED = new 

          Integer(20);

     private static final Integer SND_FORMAT_DSP_COMMANDS = new Integer(21);

     private static final Integer SND_FORMAT_DSP_COMMANDS_SAMPLES = new 

          Integer(22);

     private static final Integer SND_FORMAT_ADPCM_G721 = new Integer(23);

     private static final Integer SND_FORMAT_ADPCM_G722 = new Integer(24);

     private static final Integer SND_FORMAT_ADPCM_G723_3 = new Integer(25);

     private static final Integer SND_FORMAT_ADPCM_G723_5 = new Integer(26);

     private static final Integer SND_FORMAT_ALAW_8 = new Integer(27);

  

     private Hashtable m_htFormatInfo; 

     private int m_iBitsPerSample;

     private int m_iSampleRate;

     private int m_iChannelCount;

     private String m_szUserData;

     private FormatInfo m_fiFormatInfo;

A parser must extend the Parser class. See "Class oracle.ord.media.annotator.parsers.Parser" for more information on the fields and methods of the Parser class.

The AuParser class contains a Hashtable object named m_htFormatInfo, which will map keys to values. The keys are instantiated as private static Integer objects and given sequential values. These are specific to AuParser.java and may not be necessary for your parser.

The AuParser class contains a FormatInfo object named m_fiFormatInfo, which is used to encapsulate information related to a specific data format. See Section 6.5 for more information. These are specific to the AuParser.java example and may not be necessary for your parser.

The AuParser class also contains the following instance variables:

6.5 FormatInfo Class

Example 6-4 shows the contents of the FormatInfo class, which is used to encapsulate information related to a specific data format.

Example 6-4 FormatInfo Class

private class FormatInfo{

 [1] private String m_szFormatString;

     private String m_szFormatCode;


 [2] public FormatInfo(String szFormatString, String szFormatCode){

          m_szFormatString = szFormatString;

          m_szFormatCode = szFormatCode;

     }


 [3] public String getFormatString(){

          return m_szFormatString;

     }


 [4] public String getFormatCode (){

          return m_szFormatCode;

     }

}

The FormatInfo class contains the following code:

  1. Two instance variables that store values for the format string and format code.

  2. A constructor with two parameters that set the format string and the format code.

  3. A method that returns the format string to the caller.

  4. A method that returns the format code to the caller.

6.6 AuParser( ) Method

Example 6-5 shows the contents of the AuParser( ) method, which is the constructor of this class.

Example 6-5 AuParser( ) Method

public AuParser(){ 

   [1] m_htFormatInfo = new Hashtable();

   [2] FillFormatHashTable();

}

A parser must have a constructor with no parameters.

The code in the AuParser( ) method performs the following operations:

  1. Instantiates the m_htFormatInfo object.

  2. Populates the m_htFormatInfo object with data by calling the FillFormatHashTable( ) method. See Example 6-9 for more information.

6.7 parse( ) Method

Example 6-6 shows the parse( ) method, which parses an AU file and extracts some of its metadata.

Example 6-6 parse( ) Method

public void parse() throws ParserException{

     try {

  [1]     int iMagicNumber = m_madisResource.readInt();


  [2]     if(iMagicNumber != ((int)0x2e736e64))

             throw new ParserException("Format Exception. Expecting a 

                    NeXT/Sun au formatted file");


  [3]        int iDataLocation = m_madisResource.readInt();

  [4]        int iIntCounter = 2;


  [5]        m_annTaskMan.setTask(0, iDataLocation);

  [6]        m_annTaskMan.setTaskCurrent(iIntCounter*4,

               "Parsing AU Header...");


  [7]        int iDataSize = m_madisResource.readInt();

             m_annTaskMan.setTaskCurrent((++iIntCounter)*4);


  [8]        int iDataFormat = m_madisResource.readInt();

             m_annTaskMan.setTaskCurrent((++iIntCounter)*4);


  [9]        m_iSampleRate = m_madisResource.readInt();

             m_annTaskMan.setTaskCurrent((++iIntCounter)*4);


 [10]        m_iChannelCount = m_madisResource.readInt();

             m_annTaskMan.setTaskCurrent((++iIntCounter)*4);


 [11]        int iInfoLength = iDataLocation - 24;

             m_szUserData = m_madisResource.readString(iInfoLength);

 [12]        m_annTaskMan.setTaskCurrent(iDataLocation);

 [13]        m_annTaskMan.done();


 [14]        m_fiFormatInfo = (FormatInfo) m_htFormatInfo.get

             (new Integer(iDataFormat));


 [15]        m_iBitsPerSample = 0;

 [16]        if((iDataFormat == SND_FORMAT_MULAW_8.intValue()) ||

                (iDataFormat == SND_FORMAT_LINEAR_8.intValue()) ||

                (iDataFormat == SND_FORMAT_DSP_DATA_8.intValue()) ||

                (iDataFormat == SND_FORMAT_ALAW_8.intValue()))

                m_iBitsPerSample = 8;

             else 

             if((iDataFormat == SND_FORMAT_LINEAR_16.intValue()) ||

                (iDataFormat == SND_FORMAT_DSP_DATA_16.intValue()) ||

                (iDataFormat == SND_FORMAT_EMPHASIZED.intValue()) ||

                (iDataFormat == SND_FORMAT_COMPRESSED.intValue()) ||

                (iDataFormat == SND_FORMAT_COMPRESSED_EMPHASIZED.intValue()))

                m_iBitsPerSample = 16;

             else 

             if((iDataFormat == SND_FORMAT_LINEAR_24.intValue()) ||

                (iDataFormat == SND_FORMAT_DSP_DATA_24.intValue()))

                m_iBitsPerSample = 24;

             else 

             if((iDataFormat == SND_FORMAT_LINEAR_32.intValue())   ||


                (iDataFormat == SND_FORMAT_DSP_DATA_32.intValue()) ||

                (iDataFormat == SND_FORMAT_FLOAT.intValue()) ||

                (iDataFormat == SND_FORMAT_DOUBLE.intValue()))

                m_iBitsPerSample = 32;

             else

                m_iBitsPerSample = -1;

            }

  [17]      catch(IOException ioExc) {

            throw new ParserException("IOException raised while " + 

                  "reading from input stream");

         }


  [18]   saveToAnnotation();

}

The code in the parse( ) method performs the following operations:

  1. Using the readInt( ) method, reads the first integer (the magic number) in the AU file and sets it to iMagicNumber.

    The m_madisResource field represents the MADataInputStream object. The MADataInputStream object holds the input stream that contains the AU file to be processed. See "Class oracle.ord.media.annotator.utils.MADataInputStream" for more information.

  2. Tests to see if the magic number that was just read matches the magic number of an AU file. If it does not, then the file is not an AU file and an exception is thrown.

  3. Using the readInt( ) method, reads the next integer in the m_madisResource field, which is the offset from the beginning of the stream where the media data begins, and sets it to iDataLocation.

  4. Sets a counter. Because 2 integers (8 bytes total) have already been read, the counter is set to 2.

  5. Sets the start and end value of the AnnTaskMonitor object using the AnnTaskManager.setTask( ) method. The end value is the value of iDataLocation, which is where the media data begins. This value also represents the length of the header information. See "setTask( )" for more information.

  6. Sets the current task in the AnnTaskMonitor object using the AnnTaskManager.setTaskCurrent( ) method. The current value is set to 8 (the number of bytes read), and the message is set to "Parsing AU Header..." See "setTaskCurrent(int)" for more information.

  7. Reads the next integer in the m_madisResource field, which is the number of bytes of media data in the file. Sets the value to iDataSize. Sets the task progress monitor to reflect the 4 bytes that were read.

  8. Reads the next integer in the m_madisResource field, which is the data format code. Sets the value to iDataFormat. Sets the task progress monitor to reflect the 4 bytes that were read.

  9. Reads the next integer in the m_madisResource field, which is the sampling rate of the media data in the file. Sets the value to iSampleRate. Sets the task progress monitor to reflect the 4 bytes that were read.

  10. Reads the next integer in the m_madisResource field, which is the number of channels in the media data in the file. Sets the value to iChannelCount. Sets the task progress monitor to reflect the 4 bytes that were read.

  11. Using the readString( ) method, reads the rest of the header information and sets the value to m_szUserData.

    The length of the rest of the header information is determined by subtracting the number of bytes already read (24) from the total length of the header information.

  12. Sets the value of the task progress monitor to show that all header information has been read.

  13. Ends the current task in the AnnTaskManager object.

  14. Sets the value of the m_fiFormatInfo variable by getting the appropriate value from the Hashtable object named m_htFormatInfo.

  15. Sets the value of the m_iBitsPerSample variable to zero as a default.

  16. Checks the value of the iDataFormat variable against a series of values in the m_htFormatInfo Hashtable object and sets the m_iBitsPerSample variable to the appropriate value.

  17. Catches any errors or exceptions that may have been raised in the previous steps.

  18. Calls the saveToAnnotation( ) method to save the annotation. See Section 6.8 for more information. This method should be called at the end of any implementation of the parse( ) method.

6.8 saveToAnnotation( ) Method

Example 6-7 shows the saveToAnnotation( ) method. This method should be called after the parse( ) method has successfully finished.

Example 6-7 saveToAnnotation( ) Method

public void saveToAnnotation(){

  [1]  m_annInst.setAttribute("MEDIA_SOURCE_FILE_FORMAT_CODE", "AUFF");

       m_annInst.setAttribute("MEDIA_SOURCE_FILE_FORMAT",

                              "NeXT/Sun audio file format");


  [2]  if (m_fiFormatInfo != null) {

           m_annInst.setAttribute("MEDIA_FORMAT_ENCODING", 

                                   m_fiFormatInfo.getFormatString());

           m_annInst.setAttribute("MEDIA_FORMAT_ENCODING_CODE",

                                  m_fiFormatInfo.getFormatCode());

       }


  [3]  if(m_szUserData.trim().length() != 0)

          m_annInst.setAttribute("MEDIA_USER_DATA", m_szUserData);


  [4]  m_annInst.setAttribute("AUDIO_BITS_PER_SAMPLE", 

                              new Integer(m_iBitsPerSample));

       m_annInst.setAttribute("AUDIO_SAMPLE_RATE", 

                              new Integer(m_iSampleRate));

       m_annInst.setAttribute("AUDIO_NUM_CHANNELS", 

                               new Integer(m_iChannelCount));

}

The code in the saveToAnnotation( ) method performs the following operations:

  1. Sets the MEDIA_SOURCE_FILE_FORMAT_CODE and MEDIA_SOURCE_FILE_FORMAT attributes in the annotation to the values for an AU file.

  2. If the m_fiFormatInfo variable has a value, sets its format string and format code to the MEDIA_FORMAT_ENCODING and MEDIA_FORMAT_ENCODING_CODE attributes in the annotation, respectively.

  3. If the m_szUserData variable has a value, sets it to the MEDIA_USER_DATA attribute in the annotation.

  4. Using the setAttribute( ) method, sets the values of the m_iBitsPerSample, m_iSampleRate, and m_iChannelCount variables to the AUDIO_BITS_PER_SAMPLE, AUDIO_SAMPLE_RATE, and AUDIO_NUM_CHANNELS attributes in the annotation, respectively.

To create a subannotation, a parser uses the AnnotationFactory class to create a subannotation and attach it to the m_annInst variable. However, the AuParser.java example does not create subannotations. See the QtParser.java example, which is the QuickTime parser included with interMedia Annotator for an example of a parser that creates subannotations.

6.9 extractSamples( ) Method

Example 6-8 shows the extractSamples( ) method. This method is invoked by the AnnotationHandler.extractMedia( ) method.

Example 6-8 extractSamples( ) Method

public void extractSamples() throws ParserException{

     [1] m_sStatus.Report(Status.OUTPUT_MODE_STATUS, 

                          "AuParser does not support any sample extraction.");

     [2] m_annTaskMan.done();

}

Oracle interMedia Annotator does not support sample extraction from an AU file. Instead of throwing an error or exception, this method performs the following operations:

  1. Uses the Status object and the Report( ) method to print a message stating that this parser does not support sample extraction. See "Class oracle.ord.media.annotator.utils.Status" for more information.

  2. Ends the current task with the AnnTaskManager.done( ) method. See "done( )" for more information.

See the QuickTime parser for an example of a parser that does support sample extraction.

6.10 FillFormatHashTable( ) Method

Example 6-9 shows the FillFormatHashTable( ) method, which uses the Hashtable.put( ) method to assign a value to each key in the m_htFormatString Hashtable object. See the Java 1.2 documentation for more information. This method is specific to the AuParser.java example and may not be needed for your parser.

Example 6-9 FillFormatHashTable( ) Method

private void FillFormatHashTable(){

   m_htFormatInfo.put(SND_FORMAT_UNSPECIFIED, 

                      new FormatInfo("unspecified format", "UNSPECIFIED"));

   m_htFormatInfo.put(SND_FORMAT_MULAW_8, 

                      new FormatInfo("8-bit mu-law samples", "MULAW"));

   m_htFormatInfo.put(SND_FORMAT_LINEAR_8, 

                      new FormatInfo("8-bit linear samples", "LINEAR"));

   m_htFormatInfo.put(SND_FORMAT_LINEAR_16, 

                      new FormatInfo("16-bit linear samples", "LINEAR"));

   m_htFormatInfo.put(SND_FORMAT_LINEAR_24, 

                      new FormatInfo("24-bit linear samples", "LINEAR"));

   m_htFormatInfo.put(SND_FORMAT_LINEAR_32, 

                      new FormatInfo("32-bit linear samples", "LINEAR"));

   m_htFormatInfo.put(SND_FORMAT_FLOAT, 

                      new FormatInfo("floating-point samples", "FLOAT"));

   m_htFormatInfo.put(SND_FORMAT_DOUBLE, 

                      new FormatInfo("double-precision float samples",

                      "DOUBLE"));

   m_htFormatInfo.put(SND_FORMAT_INDIRECT, 

                      new FormatInfo("fragmented sampled data","FRAGMENTED"));

   m_htFormatInfo.put(SND_FORMAT_NESTED, 

                      new FormatInfo("nested format", "NESTED"));

   m_htFormatInfo.put(SND_FORMAT_DSP_CORE, 

                      new FormatInfo("DSP program", "DSP CORE"));

   m_htFormatInfo.put(SND_FORMAT_DSP_DATA_8, 

                      new FormatInfo("8-bit fixed-point samples","DSP_DATA")); 

   m_htFormatInfo.put(SND_FORMAT_DSP_DATA_16,

                      new FormatInfo("16-bit fixed-point samples","DSP_DATA"));

   m_htFormatInfo.put(SND_FORMAT_DSP_DATA_24, 

                      new FormatInfo("24-bit fixed-point samples","DSP_DATA")); 

   m_htFormatInfo.put(SND_FORMAT_DSP_DATA_32, 

                      new FormatInfo("32-bit fixed-point samples", "DSP_DATA"));

   m_htFormatInfo.put(SND_FORMAT_UNKNOWN, 

                      new FormatInfo("unknown au format", "UNKNOWN"));

   m_htFormatInfo.put(SND_FORMAT_DISPLAY, 

                      new FormatInfo("non-audio display data", "DISPLAY"));

   m_htFormatInfo.put(SND_FORMAT_MULAW_SQUELCH, 

                      new FormatInfo("squelch format", "MULAW_SQUELCH"));

   m_htFormatInfo.put(SND_FORMAT_EMPHASIZED, 

                      new FormatInfo("16-bit linear with emphasis",

                                     "EMPHASIZED"));

   m_htFormatInfo.put(SND_FORMAT_COMPRESSED, 

                      new FormatInfo("16-bit linear with compression",

                                     "COMPRESSED"));

   m_htFormatInfo.put(SND_FORMAT_COMPRESSED_EMPHASIZED, 

                   new FormatInfo("16-bit linear with emphasis and compression",

                                  "COMPRESSED_EMPHASIZED"));

   m_htFormatInfo.put(SND_FORMAT_DSP_COMMANDS, 

                      new FormatInfo("Music Kit DSP commands","DSP_COMMANDS"));

   m_htFormatInfo.put(SND_FORMAT_DSP_COMMANDS_SAMPLES, 

                      new FormatInfo("DSP commands samples", 

                                     "DSP_COMMANDS_SAMPLES"));

   m_htFormatInfo.put(SND_FORMAT_ADPCM_G721, 

                      new FormatInfo("adpcm G721","ADPCM_G721"));

   m_htFormatInfo.put(SND_FORMAT_ADPCM_G722, 

                      new FormatInfo("adpcm G722", "ADPCM_G722"));

   m_htFormatInfo.put(SND_FORMAT_ADPCM_G723_3, 

                      new FormatInfo("adpcm G723_3", "ADPCM_G723_3"));

   m_htFormatInfo.put(SND_FORMAT_ADPCM_G723_5, 

                      new FormatInfo("adpcm G723_5", "ADPCM_G723_5"));

   m_htFormatInfo.put(SND_FORMAT_ALAW_8, 

                      new FormatInfo("8-bit a-law samples","ALAW"));

}





Previous Next
Oracle Logo
Copyright © 1999,  2002 Oracle Corporation

All rights reserved
Go To Documentation Library
Home
Go To Product List
Book List
Go To Table Of Contents
Contents
Go To Index
Index

Master Index

Feedback