Home | History | Annotate | Download | only in media
      1 /*
      2  **
      3  ** Copyright 2010, The Android Open Source Project.
      4  **
      5  ** Licensed under the Apache License, Version 2.0 (the "License");
      6  ** you may not use this file except in compliance with the License.
      7  ** You may obtain a copy of the License at
      8  **
      9  **     http://www.apache.org/licenses/LICENSE-2.0
     10  **
     11  ** Unless required by applicable law or agreed to in writing, software
     12  ** distributed under the License is distributed on an "AS IS" BASIS,
     13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  ** See the License for the specific language governing permissions and
     15  ** limitations under the License.
     16  */
     17 
     18 #ifndef ANDROID_MEDIAPROFILES_H
     19 #define ANDROID_MEDIAPROFILES_H
     20 
     21 #include <utils/threads.h>
     22 #include <media/mediarecorder.h>
     23 
     24 namespace android {
     25 
     26 enum camcorder_quality {
     27     CAMCORDER_QUALITY_LIST_START = 0,
     28     CAMCORDER_QUALITY_LOW  = 0,
     29     CAMCORDER_QUALITY_HIGH = 1,
     30     CAMCORDER_QUALITY_QCIF = 2,
     31     CAMCORDER_QUALITY_CIF = 3,
     32     CAMCORDER_QUALITY_480P = 4,
     33     CAMCORDER_QUALITY_720P = 5,
     34     CAMCORDER_QUALITY_1080P = 6,
     35     CAMCORDER_QUALITY_QVGA = 7,
     36     CAMCORDER_QUALITY_2160P = 8,
     37     CAMCORDER_QUALITY_VGA = 9,
     38     CAMCORDER_QUALITY_4KDCI = 10,
     39     CAMCORDER_QUALITY_QHD = 11,
     40     CAMCORDER_QUALITY_2k = 12,
     41     CAMCORDER_QUALITY_LIST_END = 12,
     42 
     43     CAMCORDER_QUALITY_TIME_LAPSE_LIST_START = 1000,
     44     CAMCORDER_QUALITY_TIME_LAPSE_LOW  = 1000,
     45     CAMCORDER_QUALITY_TIME_LAPSE_HIGH = 1001,
     46     CAMCORDER_QUALITY_TIME_LAPSE_QCIF = 1002,
     47     CAMCORDER_QUALITY_TIME_LAPSE_CIF = 1003,
     48     CAMCORDER_QUALITY_TIME_LAPSE_480P = 1004,
     49     CAMCORDER_QUALITY_TIME_LAPSE_720P = 1005,
     50     CAMCORDER_QUALITY_TIME_LAPSE_1080P = 1006,
     51     CAMCORDER_QUALITY_TIME_LAPSE_QVGA = 1007,
     52     CAMCORDER_QUALITY_TIME_LAPSE_2160P = 1008,
     53     CAMCORDER_QUALITY_TIME_LAPSE_VGA = 1009,
     54     CAMCORDER_QUALITY_TIME_LAPSE_4KDCI = 1010,
     55     CAMCORDER_QUALITY_TIME_LAPSE_QHD = 1011,
     56     CAMCORDER_QUALITY_TIME_LAPSE_2k = 1012,
     57     CAMCORDER_QUALITY_TIME_LAPSE_LIST_END = 1012,
     58 
     59     CAMCORDER_QUALITY_HIGH_SPEED_LIST_START = 2000,
     60     CAMCORDER_QUALITY_HIGH_SPEED_LOW  = 2000,
     61     CAMCORDER_QUALITY_HIGH_SPEED_HIGH = 2001,
     62     CAMCORDER_QUALITY_HIGH_SPEED_480P = 2002,
     63     CAMCORDER_QUALITY_HIGH_SPEED_720P = 2003,
     64     CAMCORDER_QUALITY_HIGH_SPEED_1080P = 2004,
     65     CAMCORDER_QUALITY_HIGH_SPEED_2160P = 2005,
     66     CAMCORDER_QUALITY_HIGH_SPEED_CIF = 2006,
     67     CAMCORDER_QUALITY_HIGH_SPEED_VGA = 2007,
     68     CAMCORDER_QUALITY_HIGH_SPEED_4KDCI = 2008,
     69     CAMCORDER_QUALITY_HIGH_SPEED_LIST_END = 2008,
     70 };
     71 
     72 enum video_decoder {
     73     VIDEO_DECODER_WMV,
     74 };
     75 
     76 enum audio_decoder {
     77     AUDIO_DECODER_WMA,
     78 };
     79 
     80 
     81 class MediaProfiles
     82 {
     83 public:
     84 
     85     /*
     86      * If property media.settings.xml is not set:
     87      *
     88      * getInstance() will search through paths listed in xmlFiles.
     89      * The search goes through members of xmlFiles in the order that they are
     90      * defined, so files at lower indices have higher priority than those at
     91      * higher indices.
     92      *
     93      * TODO: Add runtime validation of xml files. A search should be considered
     94      * successful only when validation is successful.
     95      */
     96     static constexpr char const * const xmlFiles[] = {
     97             "odm/etc/media_profiles_V1_0.xml",
     98             "vendor/etc/media_profiles_V1_0.xml",
     99             "system/etc/media_profiles.xml"
    100             };
    101 
    102     /**
    103      * Returns the singleton instance for subsequence queries or NULL if error.
    104      *
    105      * If property media.settings.xml is set, getInstance() will attempt to read
    106      * from file path in media.settings.xml. Otherwise, getInstance() will
    107      * search through the list xmlFiles as described above.
    108      *
    109      * If the search is unsuccessful, the default instance will be created
    110      * instead.
    111      *
    112      * TODO: After validation is added, getInstance() should handle validation
    113      * failure properly.
    114      */
    115     static MediaProfiles* getInstance();
    116 
    117     /**
    118      * Returns the value for the given param name for the given camera at
    119      * the given quality level, or -1 if error.
    120      *
    121      * Supported param name are:
    122      * duration - the recording duration.
    123      * file.format - output file format. see mediarecorder.h for details
    124      * vid.codec - video encoder. see mediarecorder.h for details.
    125      * aud.codec - audio encoder. see mediarecorder.h for details.
    126      * vid.width - video frame width
    127      * vid.height - video frame height
    128      * vid.fps - video frame rate
    129      * vid.bps - video bit rate
    130      * aud.bps - audio bit rate
    131      * aud.hz - audio sample rate
    132      * aud.ch - number of audio channels
    133      */
    134     int getCamcorderProfileParamByName(const char *name, int cameraId,
    135                                        camcorder_quality quality) const;
    136 
    137     /**
    138      * Returns true if a profile for the given camera at the given quality exists,
    139      * or false if not.
    140      */
    141     bool hasCamcorderProfile(int cameraId, camcorder_quality quality) const;
    142 
    143     /**
    144      * Returns the output file formats supported.
    145      */
    146     Vector<output_format> getOutputFileFormats() const;
    147 
    148     /**
    149      * Returns the video encoders supported.
    150      */
    151     Vector<video_encoder> getVideoEncoders() const;
    152 
    153     /**
    154      * Returns the value for the given param name for the given video encoder
    155      * returned from getVideoEncoderByIndex or -1 if error.
    156      *
    157      * Supported param name are:
    158      * enc.vid.width.min - min video frame width
    159      * enc.vid.width.max - max video frame width
    160      * enc.vid.height.min - min video frame height
    161      * enc.vid.height.max - max video frame height
    162      * enc.vid.bps.min - min bit rate in bits per second
    163      * enc.vid.bps.max - max bit rate in bits per second
    164      * enc.vid.fps.min - min frame rate in frames per second
    165      * enc.vid.fps.max - max frame rate in frames per second
    166      */
    167     int getVideoEncoderParamByName(const char *name, video_encoder codec) const;
    168 
    169     /**
    170      * Returns the audio encoders supported.
    171      */
    172     Vector<audio_encoder> getAudioEncoders() const;
    173 
    174     /**
    175      * Returns the value for the given param name for the given audio encoder
    176      * returned from getAudioEncoderByIndex or -1 if error.
    177      *
    178      * Supported param name are:
    179      * enc.aud.ch.min - min number of channels
    180      * enc.aud.ch.max - max number of channels
    181      * enc.aud.bps.min - min bit rate in bits per second
    182      * enc.aud.bps.max - max bit rate in bits per second
    183      * enc.aud.hz.min - min sample rate in samples per second
    184      * enc.aud.hz.max - max sample rate in samples per second
    185      */
    186     int getAudioEncoderParamByName(const char *name, audio_encoder codec) const;
    187 
    188     /**
    189       * Returns the video decoders supported.
    190       */
    191     Vector<video_decoder> getVideoDecoders() const;
    192 
    193      /**
    194       * Returns the audio decoders supported.
    195       */
    196     Vector<audio_decoder> getAudioDecoders() const;
    197 
    198     /**
    199      * Returns the number of image encoding quality levels supported.
    200      */
    201     Vector<int> getImageEncodingQualityLevels(int cameraId) const;
    202 
    203     /**
    204      * Returns the start time offset (in ms) for the given camera Id.
    205      * If the given camera Id does not exist, -1 will be returned.
    206      */
    207     int getStartTimeOffsetMs(int cameraId) const;
    208 
    209 private:
    210     enum {
    211         // Camcorder profiles (high/low) and timelapse profiles (high/low)
    212         kNumRequiredProfiles = 4,
    213     };
    214 
    215     MediaProfiles& operator=(const MediaProfiles&);  // Don't call me
    216     MediaProfiles(const MediaProfiles&);             // Don't call me
    217     MediaProfiles() {}                               // Dummy default constructor
    218     ~MediaProfiles();                                // Don't delete me
    219 
    220     struct VideoCodec {
    221         VideoCodec(video_encoder codec, int bitRate, int frameWidth, int frameHeight, int frameRate)
    222             : mCodec(codec),
    223               mBitRate(bitRate),
    224               mFrameWidth(frameWidth),
    225               mFrameHeight(frameHeight),
    226               mFrameRate(frameRate) {}
    227 
    228         VideoCodec(const VideoCodec& copy) {
    229             mCodec = copy.mCodec;
    230             mBitRate = copy.mBitRate;
    231             mFrameWidth = copy.mFrameWidth;
    232             mFrameHeight = copy.mFrameHeight;
    233             mFrameRate = copy.mFrameRate;
    234         }
    235 
    236         ~VideoCodec() {}
    237 
    238         video_encoder mCodec;
    239         int mBitRate;
    240         int mFrameWidth;
    241         int mFrameHeight;
    242         int mFrameRate;
    243     };
    244 
    245     struct AudioCodec {
    246         AudioCodec(audio_encoder codec, int bitRate, int sampleRate, int channels)
    247             : mCodec(codec),
    248               mBitRate(bitRate),
    249               mSampleRate(sampleRate),
    250               mChannels(channels) {}
    251 
    252         AudioCodec(const AudioCodec& copy) {
    253             mCodec = copy.mCodec;
    254             mBitRate = copy.mBitRate;
    255             mSampleRate = copy.mSampleRate;
    256             mChannels = copy.mChannels;
    257         }
    258 
    259         ~AudioCodec() {}
    260 
    261         audio_encoder mCodec;
    262         int mBitRate;
    263         int mSampleRate;
    264         int mChannels;
    265     };
    266 
    267     struct CamcorderProfile {
    268         CamcorderProfile()
    269             : mCameraId(0),
    270               mFileFormat(OUTPUT_FORMAT_THREE_GPP),
    271               mQuality(CAMCORDER_QUALITY_HIGH),
    272               mDuration(0),
    273               mVideoCodec(0),
    274               mAudioCodec(0) {}
    275 
    276         CamcorderProfile(const CamcorderProfile& copy) {
    277             mCameraId = copy.mCameraId;
    278             mFileFormat = copy.mFileFormat;
    279             mQuality = copy.mQuality;
    280             mDuration = copy.mDuration;
    281             mVideoCodec = new VideoCodec(*copy.mVideoCodec);
    282             mAudioCodec = new AudioCodec(*copy.mAudioCodec);
    283         }
    284 
    285         ~CamcorderProfile() {
    286             delete mVideoCodec;
    287             delete mAudioCodec;
    288         }
    289 
    290         int mCameraId;
    291         output_format mFileFormat;
    292         camcorder_quality mQuality;
    293         int mDuration;
    294         VideoCodec *mVideoCodec;
    295         AudioCodec *mAudioCodec;
    296     };
    297 
    298     struct VideoEncoderCap {
    299         // Ugly constructor
    300         VideoEncoderCap(video_encoder codec,
    301                         int minBitRate, int maxBitRate,
    302                         int minFrameWidth, int maxFrameWidth,
    303                         int minFrameHeight, int maxFrameHeight,
    304                         int minFrameRate, int maxFrameRate)
    305             : mCodec(codec),
    306               mMinBitRate(minBitRate), mMaxBitRate(maxBitRate),
    307               mMinFrameWidth(minFrameWidth), mMaxFrameWidth(maxFrameWidth),
    308               mMinFrameHeight(minFrameHeight), mMaxFrameHeight(maxFrameHeight),
    309               mMinFrameRate(minFrameRate), mMaxFrameRate(maxFrameRate) {}
    310 
    311          ~VideoEncoderCap() {}
    312 
    313         video_encoder mCodec;
    314         int mMinBitRate, mMaxBitRate;
    315         int mMinFrameWidth, mMaxFrameWidth;
    316         int mMinFrameHeight, mMaxFrameHeight;
    317         int mMinFrameRate, mMaxFrameRate;
    318     };
    319 
    320     struct AudioEncoderCap {
    321         // Ugly constructor
    322         AudioEncoderCap(audio_encoder codec,
    323                         int minBitRate, int maxBitRate,
    324                         int minSampleRate, int maxSampleRate,
    325                         int minChannels, int maxChannels)
    326             : mCodec(codec),
    327               mMinBitRate(minBitRate), mMaxBitRate(maxBitRate),
    328               mMinSampleRate(minSampleRate), mMaxSampleRate(maxSampleRate),
    329               mMinChannels(minChannels), mMaxChannels(maxChannels) {}
    330 
    331         ~AudioEncoderCap() {}
    332 
    333         audio_encoder mCodec;
    334         int mMinBitRate, mMaxBitRate;
    335         int mMinSampleRate, mMaxSampleRate;
    336         int mMinChannels, mMaxChannels;
    337     };
    338 
    339     struct VideoDecoderCap {
    340         VideoDecoderCap(video_decoder codec): mCodec(codec) {}
    341         ~VideoDecoderCap() {}
    342 
    343         video_decoder mCodec;
    344     };
    345 
    346     struct AudioDecoderCap {
    347         AudioDecoderCap(audio_decoder codec): mCodec(codec) {}
    348         ~AudioDecoderCap() {}
    349 
    350         audio_decoder mCodec;
    351     };
    352 
    353     struct NameToTagMap {
    354         const char* name;
    355         int tag;
    356     };
    357 
    358     struct ImageEncodingQualityLevels {
    359         int mCameraId;
    360         Vector<int> mLevels;
    361     };
    362 
    363     int getCamcorderProfileIndex(int cameraId, camcorder_quality quality) const;
    364     void initRequiredProfileRefs(const Vector<int>& cameraIds);
    365     int getRequiredProfileRefIndex(int cameraId);
    366 
    367     // Debug
    368     static void logVideoCodec(const VideoCodec& codec);
    369     static void logAudioCodec(const AudioCodec& codec);
    370     static void logVideoEncoderCap(const VideoEncoderCap& cap);
    371     static void logAudioEncoderCap(const AudioEncoderCap& cap);
    372     static void logVideoDecoderCap(const VideoDecoderCap& cap);
    373     static void logAudioDecoderCap(const AudioDecoderCap& cap);
    374 
    375     // Returns true if xmlFile exists.
    376     // TODO: Add runtime validation.
    377     static bool checkXmlFile(const char* xmlFile);
    378 
    379     // If the xml configuration file does exist, use the settings
    380     // from the xml
    381     static MediaProfiles* createInstanceFromXmlFile(const char *xml);
    382     static output_format createEncoderOutputFileFormat(const char **atts);
    383     static VideoCodec* createVideoCodec(const char **atts, MediaProfiles *profiles);
    384     static AudioCodec* createAudioCodec(const char **atts, MediaProfiles *profiles);
    385     static AudioDecoderCap* createAudioDecoderCap(const char **atts);
    386     static VideoDecoderCap* createVideoDecoderCap(const char **atts);
    387     static VideoEncoderCap* createVideoEncoderCap(const char **atts);
    388     static AudioEncoderCap* createAudioEncoderCap(const char **atts);
    389 
    390     static CamcorderProfile* createCamcorderProfile(
    391                 int cameraId, const char **atts, Vector<int>& cameraIds);
    392 
    393     static int getCameraId(const char **atts);
    394 
    395     void addStartTimeOffset(int cameraId, const char **atts);
    396 
    397     ImageEncodingQualityLevels* findImageEncodingQualityLevels(int cameraId) const;
    398     void addImageEncodingQualityLevel(int cameraId, const char** atts);
    399 
    400     // Customized element tag handler for parsing the xml configuration file.
    401     static void startElementHandler(void *userData, const char *name, const char **atts);
    402 
    403     // If the xml configuration file does not exist, use hard-coded values
    404     static MediaProfiles* createDefaultInstance();
    405 
    406     static CamcorderProfile *createDefaultCamcorderQcifProfile(camcorder_quality quality);
    407     static CamcorderProfile *createDefaultCamcorderCifProfile(camcorder_quality quality);
    408     static void createDefaultCamcorderLowProfiles(
    409             MediaProfiles::CamcorderProfile **lowProfile,
    410             MediaProfiles::CamcorderProfile **lowSpecificProfile);
    411     static void createDefaultCamcorderHighProfiles(
    412             MediaProfiles::CamcorderProfile **highProfile,
    413             MediaProfiles::CamcorderProfile **highSpecificProfile);
    414 
    415     static CamcorderProfile *createDefaultCamcorderTimeLapseQcifProfile(camcorder_quality quality);
    416     static CamcorderProfile *createDefaultCamcorderTimeLapse480pProfile(camcorder_quality quality);
    417     static void createDefaultCamcorderTimeLapseLowProfiles(
    418             MediaProfiles::CamcorderProfile **lowTimeLapseProfile,
    419             MediaProfiles::CamcorderProfile **lowSpecificTimeLapseProfile);
    420     static void createDefaultCamcorderTimeLapseHighProfiles(
    421             MediaProfiles::CamcorderProfile **highTimeLapseProfile,
    422             MediaProfiles::CamcorderProfile **highSpecificTimeLapseProfile);
    423 
    424     static void createDefaultCamcorderProfiles(MediaProfiles *profiles);
    425     static void createDefaultVideoEncoders(MediaProfiles *profiles);
    426     static void createDefaultAudioEncoders(MediaProfiles *profiles);
    427     static void createDefaultVideoDecoders(MediaProfiles *profiles);
    428     static void createDefaultAudioDecoders(MediaProfiles *profiles);
    429     static void createDefaultEncoderOutputFileFormats(MediaProfiles *profiles);
    430     static void createDefaultImageEncodingQualityLevels(MediaProfiles *profiles);
    431     static void createDefaultImageDecodingMaxMemory(MediaProfiles *profiles);
    432 
    433     static VideoEncoderCap* createDefaultH263VideoEncoderCap();
    434     static VideoEncoderCap* createDefaultM4vVideoEncoderCap();
    435     static AudioEncoderCap* createDefaultAmrNBEncoderCap();
    436 
    437     static int findTagForName(const NameToTagMap *map, size_t nMappings, const char *name);
    438 
    439     /**
    440      * Check on existing profiles with the following criteria:
    441      * 1. Low quality profile must have the lowest video
    442      *    resolution product (width x height)
    443      * 2. High quality profile must have the highest video
    444      *    resolution product (width x height)
    445      *
    446      * and add required low/high quality camcorder/timelapse
    447      * profiles if they are not found. This allows to remove
    448      * duplicate profile definitions in the media_profiles.xml
    449      * file.
    450      */
    451     void checkAndAddRequiredProfilesIfNecessary();
    452 
    453 
    454     // Mappings from name (for instance, codec name) to enum value
    455     static const NameToTagMap sVideoEncoderNameMap[];
    456     static const NameToTagMap sAudioEncoderNameMap[];
    457     static const NameToTagMap sFileFormatMap[];
    458     static const NameToTagMap sVideoDecoderNameMap[];
    459     static const NameToTagMap sAudioDecoderNameMap[];
    460     static const NameToTagMap sCamcorderQualityNameMap[];
    461 
    462     static bool sIsInitialized;
    463     static MediaProfiles *sInstance;
    464     static Mutex sLock;
    465     int mCurrentCameraId;
    466 
    467     Vector<CamcorderProfile*> mCamcorderProfiles;
    468     Vector<AudioEncoderCap*>  mAudioEncoders;
    469     Vector<VideoEncoderCap*>  mVideoEncoders;
    470     Vector<AudioDecoderCap*>  mAudioDecoders;
    471     Vector<VideoDecoderCap*>  mVideoDecoders;
    472     Vector<output_format>     mEncoderOutputFileFormats;
    473     Vector<ImageEncodingQualityLevels *>  mImageEncodingQualityLevels;
    474     KeyedVector<int, int> mStartTimeOffsets;
    475 
    476     typedef struct {
    477         bool mHasRefProfile;      // Refers to an existing profile
    478         int  mRefProfileIndex;    // Reference profile index
    479         int  mResolutionProduct;  // width x height
    480     } RequiredProfileRefInfo;     // Required low and high profiles
    481 
    482     typedef struct {
    483         RequiredProfileRefInfo mRefs[kNumRequiredProfiles];
    484         int mCameraId;
    485     } RequiredProfiles;
    486 
    487     RequiredProfiles *mRequiredProfileRefs;
    488     Vector<int>              mCameraIds;
    489 };
    490 
    491 }; // namespace android
    492 
    493 #endif // ANDROID_MEDIAPROFILES_H
    494