OSDN Git Service

cleanup FFmpegExtractor::stream_component_open
[android-x86/external-stagefright-plugins.git] / utils / codec_utils.cpp
index 8afc79e..cc6a343 100644 (file)
 #define LOG_TAG "codec_utils"
 #include <utils/Log.h>
 
-#include <utils/Errors.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "config.h"
+#include "libavcodec/xiph.h"
 
+#ifdef __cplusplus
+}
+#endif
+
+#include <utils/Errors.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
+#include "include/avc_utils.h"
 
 #include "codec_utils.h"
 
@@ -40,7 +51,7 @@ static void EncodeSize14(uint8_t **_ptr, size_t size) {
     *_ptr = ptr;
 }
 
-sp<ABuffer> MakeMPEGVideoESDS(const sp<ABuffer> &csd) {
+static sp<ABuffer> MakeMPEGVideoESDS(const sp<ABuffer> &csd) {
     sp<ABuffer> esds = new ABuffer(csd->size() + 25);
 
     uint8_t *ptr = esds->data();
@@ -70,7 +81,7 @@ sp<ABuffer> MakeMPEGVideoESDS(const sp<ABuffer> &csd) {
 }
 
 //Returns the sample rate based on the sampling frequency index
-uint32_t getAACSampleRate(const uint8_t sf_index)
+static uint32_t getAACSampleRate(const uint8_t sf_index)
 {
     static const uint32_t sample_rates[] =
     {
@@ -85,6 +96,372 @@ uint32_t getAACSampleRate(const uint8_t sf_index)
     return 0;
 }
 
+//video
+
+//H.264 Video Types
+//http://msdn.microsoft.com/en-us/library/dd757808(v=vs.85).aspx
+
+// H.264 bitstream without start codes.
+sp<MetaData> setAVCFormat(AVCodecContext *avctx)
+{
+    ALOGV("AVC");
+
+       CHECK_EQ(avctx->codec_id, AV_CODEC_ID_H264);
+       CHECK_GT(avctx->extradata_size, 0);
+       CHECK_EQ(avctx->extradata[0], 1); //configurationVersion
+
+    if (avctx->width == 0 || avctx->height == 0) {
+         int32_t width, height;
+         sp<ABuffer> seqParamSet = new ABuffer(avctx->extradata_size - 8);
+         memcpy(seqParamSet->data(), avctx->extradata + 8, avctx->extradata_size - 8);
+         FindAVCDimensions(seqParamSet, &width, &height);
+         avctx->width  = width;
+         avctx->height = height;
+     }
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+    meta->setData(kKeyAVCC, kTypeAVCC, avctx->extradata, avctx->extradata_size);
+
+       return meta;
+}
+
+// H.264 bitstream with start codes.
+sp<MetaData> setH264Format(AVCodecContext *avctx)
+{
+    ALOGV("H264");
+
+       CHECK_EQ(avctx->codec_id, AV_CODEC_ID_H264);
+       CHECK_NE(avctx->extradata[0], 1); //configurationVersion
+
+    sp<ABuffer> buffer = new ABuffer(avctx->extradata_size);
+    memcpy(buffer->data(), avctx->extradata, avctx->extradata_size);
+    return MakeAVCCodecSpecificData(buffer);
+}
+
+sp<MetaData> setMPEG4Format(AVCodecContext *avctx)
+{
+    ALOGV("MPEG4");
+
+    sp<ABuffer> csd = new ABuffer(avctx->extradata_size);
+    memcpy(csd->data(), avctx->extradata, avctx->extradata_size);
+    sp<ABuffer> esds = MakeMPEGVideoESDS(csd);
+
+    sp<MetaData> meta = new MetaData;
+    meta->setData(kKeyESDS, kTypeESDS, esds->data(), esds->size());
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+
+    return meta;
+}
+
+sp<MetaData> setH263Format(AVCodecContext *avctx)
+{
+    ALOGV("H263");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
+
+    return meta;
+}
+
+sp<MetaData> setMPEG2VIDEOFormat(AVCodecContext *avctx)
+{
+    ALOGV("MPEG%uVIDEO", avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ? 2 : 1);
+
+    sp<ABuffer> csd = new ABuffer(avctx->extradata_size);
+    memcpy(csd->data(), avctx->extradata, avctx->extradata_size);
+    sp<ABuffer> esds = MakeMPEGVideoESDS(csd);
+
+    sp<MetaData> meta = new MetaData;
+    meta->setData(kKeyESDS, kTypeESDS, esds->data(), esds->size());
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG2);
+
+    return meta;
+}
+
+sp<MetaData> setVC1Format(AVCodecContext *avctx)
+{
+    ALOGV("VC1");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VC1);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+
+    return meta;
+}
+
+sp<MetaData> setWMV1Format(AVCodecContext *avctx)
+{
+    ALOGV("WMV1");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_WMV);
+    meta->setInt32(kKeyWMVVersion, kTypeWMVVer_7);
+
+    return meta;
+}
+
+sp<MetaData> setWMV2Format(AVCodecContext *avctx)
+{
+    ALOGV("WMV2");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_WMV);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+    meta->setInt32(kKeyWMVVersion, kTypeWMVVer_8);
+
+    return meta;
+}
+
+sp<MetaData> setWMV3Format(AVCodecContext *avctx)
+{
+    ALOGV("WMV3");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_WMV);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+    meta->setInt32(kKeyWMVVersion, kTypeWMVVer_9);
+
+    return meta;
+}
+
+sp<MetaData> setRV20Format(AVCodecContext *avctx)
+{
+    ALOGV("RV20");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RV);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+    meta->setInt32(kKeyRVVersion, kTypeRVVer_G2); //http://en.wikipedia.org/wiki/RealVide
+
+    return meta;
+}
+
+sp<MetaData> setRV30Format(AVCodecContext *avctx)
+{
+    ALOGV("RV30");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RV);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+    meta->setInt32(kKeyRVVersion, kTypeRVVer_8); //http://en.wikipedia.org/wiki/RealVide
+
+    return meta;
+}
+
+sp<MetaData> setRV40Format(AVCodecContext *avctx)
+{
+    ALOGV("RV40");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RV);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+    meta->setInt32(kKeyRVVersion, kTypeRVVer_9); //http://en.wikipedia.org/wiki/RealVide
+
+    return meta;
+}
+
+sp<MetaData> setFLV1Format(AVCodecContext *avctx)
+{
+    ALOGV("FLV1(Sorenson H263)");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_FLV1);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+
+    return meta;
+}
+
+sp<MetaData> setHEVCFormat(AVCodecContext *avctx)
+{
+    ALOGV("HEVC");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+
+    return meta;
+}
+
+//audio
+
+sp<MetaData> setMP2Format(AVCodecContext *avctx)
+{
+    ALOGV("MP2");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
+
+    return meta;
+}
+
+sp<MetaData> setMP3Format(AVCodecContext *avctx)
+{
+    ALOGV("MP3");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+
+    return meta;
+}
+
+sp<MetaData> setVORBISFormat(AVCodecContext *avctx)
+{
+    ALOGV("VORBIS");
+
+    uint8_t *header_start[3];
+    int header_len[3];
+    if (avpriv_split_xiph_headers(avctx->extradata,
+                avctx->extradata_size, 30,
+                header_start, header_len) < 0) {
+        ALOGE("vorbis extradata corrupt.");
+        return NULL;
+    }
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
+    //identification header
+    meta->setData(kKeyVorbisInfo,  0, header_start[0], header_len[0]);
+    //setup header
+    meta->setData(kKeyVorbisBooks, 0, header_start[2], header_len[2]);
+
+    return meta;
+}
+
+sp<MetaData> setAC3Format(AVCodecContext *avctx)
+{
+    ALOGV("AC3");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC3);
+
+    return meta;
+}
+
+sp<MetaData> setAACFormat(AVCodecContext *avctx)
+{
+    ALOGV("AAC");
+
+    uint32_t sr;
+    const uint8_t *header;
+    uint8_t profile, sf_index, channel;
+
+    header = avctx->extradata;
+    CHECK(header != NULL);
+
+    // AudioSpecificInfo follows
+    // oooo offf fccc c000
+    // o - audioObjectType
+    // f - samplingFreqIndex
+    // c - channelConfig
+    profile = ((header[0] & 0xf8) >> 3) - 1;
+    sf_index = (header[0] & 0x07) << 1 | (header[1] & 0x80) >> 7;
+    sr = getAACSampleRate(sf_index);
+    if (sr == 0) {
+        ALOGE("unsupport the aac sample rate");
+        return NULL;
+    }
+    channel = (header[1] >> 3) & 0xf;
+    ALOGV("aac profile: %d, sf_index: %d, channel: %d", profile, sf_index, channel);
+
+    sp<MetaData> meta = MakeAACCodecSpecificData(profile, sf_index, channel);
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+
+    return meta;
+}
+
+sp<MetaData> setWMAV1Format(AVCodecContext *avctx)
+{
+    ALOGV("WMAV1");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_WMA);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+    meta->setInt32(kKeyWMAVersion, kTypeWMA); //FIXME version?
+
+    return meta;
+}
+
+sp<MetaData> setWMAV2Format(AVCodecContext *avctx)
+{
+    ALOGV("WMAV2");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_WMA);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+    meta->setInt32(kKeyWMAVersion, kTypeWMA);
+
+    return meta;
+}
+
+sp<MetaData> setWMAProFormat(AVCodecContext *avctx)
+{
+    ALOGV("WMAPro");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_WMA);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+    meta->setInt32(kKeyWMAVersion, kTypeWMAPro);
+
+    return meta;
+}
+
+sp<MetaData> setWMALossLessFormat(AVCodecContext *avctx)
+{
+    ALOGV("WMALOSSLESS");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_WMA);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+    meta->setInt32(kKeyWMAVersion, kTypeWMALossLess);
+
+    return meta;
+}
+
+sp<MetaData> setRAFormat(AVCodecContext *avctx)
+{
+    ALOGV("COOK");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RA);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+
+    return meta;
+}
+
+sp<MetaData> setAPEFormat(AVCodecContext *avctx)
+{
+    ALOGV("APE");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_APE);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+
+    return meta;
+}
+
+sp<MetaData> setDTSFormat(AVCodecContext *avctx)
+{
+    ALOGV("DTS");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_DTS);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+
+    return meta;
+}
+
+sp<MetaData> setFLACFormat(AVCodecContext *avctx)
+{
+    ALOGV("FLAC");
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FLAC);
+    meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+
+    return meta;
+}
+
 //Convert H.264 NAL format to annex b
 status_t convertNal2AnnexB(uint8_t *dst, size_t dst_size,
         uint8_t *src, size_t src_size, size_t nal_len_size)