/* * Copyright (c) 2008-2016 Allwinner Technology Co. Ltd. * All rights reserved. * * File : awmetadataretriever.cpp * Description : metadataretriever * History : * */ #define LOG_TAG "awmetadataretriever" #include "cdx_log.h" #include "awmetadataretriever.h" #include "memoryAdapter.h" //#include #include #include #include #include #if (CONF_ANDROID_MAJOR_VER >= 5) #include "media/CharacterEncodingDetector.h" #endif #if (CONF_ANDROID_MAJOR_VER >= 6) #include "awMediaDataSource.h" #endif #include "unicode/ucnv.h" #include "unicode/ustring.h" #include //#include "vdecoder.h" //* video decode library in "LIBRARY/CODEC/VIDEO/DECODER" //#include "CdxParser.h" //* parser library in "LIBRARY/DEMUX/PARSER/include/" //#include "CdxStream.h" //* parser library in "LIBRARY/DEMUX/STREAM/include/" #include #include "xmetadataretriever.h" #define MediaScanDedug (0) struct Map { int from; int to; const char *name; }; static const Map kMap[] = { { kKeyMIMEType, METADATA_KEY_MIMETYPE, NULL }, { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER, "tracknumber" }, { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER, "discnumber" }, { kKeyAlbum, METADATA_KEY_ALBUM, "album" }, { kKeyArtist, METADATA_KEY_ARTIST, "artist" }, { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST, "albumartist" }, { kKeyAuthor, METADATA_KEY_AUTHOR, NULL }, { kKeyComposer, METADATA_KEY_COMPOSER, "composer" }, { kKeyDate, METADATA_KEY_DATE, NULL }, { kKeyGenre, METADATA_KEY_GENRE, "genre" }, { kKeyTitle, METADATA_KEY_TITLE, "title" }, { kKeyYear, METADATA_KEY_YEAR, "year" }, { kKeyWriter, METADATA_KEY_WRITER, "writer" }, { kKeyCompilation, METADATA_KEY_COMPILATION, "compilation" }, { kKeyLocation, METADATA_KEY_LOCATION, NULL }, }; // MIMETYPE define in libstagefright/Mediadefs.cpp const char *MEDIA_MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8"; const char *MEDIA_MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9"; const char *MEDIA_MIMETYPE_VIDEO_AVC = "video/avc"; const char *MEDIA_MIMETYPE_VIDEO_HEVC = "video/hevc"; const char *MEDIA_MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es"; const char *MEDIA_MIMETYPE_VIDEO_H263 = "video/3gpp"; const char *MEDIA_MIMETYPE_VIDEO_MPEG2 = "video/mpeg2"; const char *MEDIA_MIMETYPE_VIDEO_RAW = "video/raw"; const char *MEDIA_MIMETYPE_VIDEO_DOLBY_VISION = "video/dolby-vision"; const char *MEDIA_MIMETYPE_VIDEO_WMV1 = "video/wmv1"; const char *MEDIA_MIMETYPE_VIDEO_WMV2 = "video/wmv2"; const char *MEDIA_MIMETYPE_VIDEO_VC1 = "video/wvc1"; //const char *MEDIA_MIMETYPE_VIDEO_VC1 = "video/x-ms-wmv"; //const char *MEDIA_MIMETYPE_VIDEO_VP6 = "video/x-vp6"; const char *MEDIA_MIMETYPE_VIDEO_VP6 = "video/x-vnd.on2.vp6"; const char *MEDIA_MIMETYPE_VIDEO_S263 = "video/flv1"; const char *MEDIA_MIMETYPE_VIDEO_MJPEG = "video/jpeg"; const char *MEDIA_MIMETYPE_VIDEO_MPEG1 = "video/mpeg1"; const char *MEDIA_MIMETYPE_VIDEO_MSMPEG4V1 = "video/x-ms-mpeg4v1"; const char *MEDIA_MIMETYPE_VIDEO_MSMPEG4V2 = "video/x-ms-mpeg4v2"; const char *MEDIA_MIMETYPE_VIDEO_DIVX = "video/divx"; const char *MEDIA_MIMETYPE_VIDEO_XVID = "video/xvid"; const char *MEDIA_MIMETYPE_VIDEO_RXG2 = "video/rvg2"; const char *MEDIA_MIMETYPE_VIDEO_VPX = "video/x-vnd.on2.vp8"; const char *MEDIA_MIMETYPE_AUDIO_AMR_NB = "audio/3gpp"; const char *MEDIA_MIMETYPE_AUDIO_AMR_WB = "audio/amr-wb"; const char *MEDIA_MIMETYPE_AUDIO_MPEG = "audio/mpeg"; const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I = "audio/mpeg-L1"; const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II = "audio/mpeg-L2"; const char *MEDIA_MIMETYPE_AUDIO_MIDI = "audio/midi"; const char *MEDIA_MIMETYPE_AUDIO_AAC = "audio/mp4a-latm"; const char *MEDIA_MIMETYPE_AUDIO_QCELP = "audio/qcelp"; const char *MEDIA_MIMETYPE_AUDIO_VORBIS = "audio/vorbis"; const char *MEDIA_MIMETYPE_AUDIO_OPUS = "audio/opus"; const char *MEDIA_MIMETYPE_AUDIO_G711_ALAW = "audio/g711-alaw"; const char *MEDIA_MIMETYPE_AUDIO_G711_MLAW = "audio/g711-mlaw"; const char *MEDIA_MIMETYPE_AUDIO_RAW = "audio/raw"; const char *MEDIA_MIMETYPE_AUDIO_FLAC = "audio/flac"; const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS = "audio/aac-adts"; const char *MEDIA_MIMETYPE_AUDIO_MSGSM = "audio/gsm"; const char *MEDIA_MIMETYPE_AUDIO_AC3 = "audio/ac3"; const char *MEDIA_MIMETYPE_AUDIO_EAC3 = "audio/eac3"; const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mp4"; const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/x-wav"; const char *MEDIA_MIMETYPE_CONTAINER_OGG = "application/ogg"; const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA = "video/x-matroska"; const char *MEDIA_MIMETYPE_CONTAINER_MPEG2TS = "video/mp2ts"; const char *MEDIA_MIMETYPE_CONTAINER_AVI = "video/avi"; const char *MEDIA_MIMETYPE_CONTAINER_MPEG2PS = "video/mp2p"; const char *MEDIA_MIMETYPE_CONTAINER_WVM = "video/wvm"; const char *MEDIA_MIMETYPE_TEXT_3GPP = "text/3gpp-tt"; const char *MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip"; const char *MEDIA_MIMETYPE_TEXT_VTT = "text/vtt"; const char *MEDIA_MIMETYPE_TEXT_CEA_608 = "text/cea-608"; const char *MEDIA_MIMETYPE_TEXT_CEA_708 = "text/cea-708"; const char *MEDIA_MIMETYPE_DATA_TIMED_ID3 = "application/x-id3v4"; static cdx_int32 kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]); #if SAVE_BITSTREAM const char* bitstreamPath = "/data/camera/out.h264"; static FILE* fph264 = NULL; #endif /* process 4096 packets to get a frame at maximum. */ #define MAX_PACKET_COUNT_TO_GET_A_FRAME 4096 /* use 5 seconds to get a frame at maximum. */ #define MAX_TIME_TO_GET_A_FRAME 5000000 /* use 10 seconds to get a stream at maximum. */ #define MAX_TIME_TO_GET_A_STREAM 10000000 #define MAX_OUTPUT_STREAM_SIZE (1024*1024) typedef struct MetadataPriData{ CdxDataSourceT mSource; CdxMediaInfoT mMediaInfo; int mCancelPrepareFlag; MediaAlbumArt* mAlbumArtPic; KeyedVector* mMetaData; #if MediaScanDedug int mFd; #endif XRetriever *mXRetriever; CdxKeyedVectorT *mHeader; #if (CONF_ANDROID_MAJOR_VER >= 6) sp mDataSource; CdxStreamT* mStream; #endif }MetadataPriData; static int parseHeaders(CdxKeyedVectorT **header, char *uri, KeyedVector* pHeaders); static void clearHeaders(CdxKeyedVectorT **header); static int64_t GetSysTime(); static int metafindCStringByKey(CdxMediaInfoT* mediaInfo, int key, cdx_uint8** value); AwMetadataRetriever::AwMetadataRetriever() { logd("AwMetadataRetriever Create."); //AwPluginInit(); //TODO: add plugin in config proc mPriData = (MetadataPriData*)malloc(sizeof(MetadataPriData)); memset(mPriData,0x00,sizeof(MetadataPriData)); mPriData->mCancelPrepareFlag = 0; mPriData->mAlbumArtPic = NULL; #if (CONF_ANDROID_MAJOR_VER >= 6) mPriData->mDataSource = NULL; mPriData->mStream = NULL; #endif #if MediaScanDedug mPriData->mFd = 0; #endif memset(&mPriData->mSource, 0, sizeof(CdxDataSourceT)); mPriData->mMetaData = new KeyedVector(); mPriData->mXRetriever = XRetrieverCreate(); if (mPriData->mXRetriever == NULL) { loge("XRetrieverCreate failed."); if (mPriData->mMetaData) { delete mPriData->mMetaData; mPriData->mMetaData = NULL; } free(mPriData); mPriData = NULL; } } AwMetadataRetriever::~AwMetadataRetriever() { mPriData->mCancelPrepareFlag = 1; clear(); if (mPriData->mMetaData) { delete mPriData->mMetaData; mPriData->mMetaData = NULL; } if (mPriData->mXRetriever) { XRetrieverDestory(mPriData->mXRetriever); } #if (CONF_ANDROID_MAJOR_VER >= 6) if((mPriData->mStream != NULL) && (mPriData->mDataSource != NULL)) { MediaDataSourceClose(mPriData->mStream); mPriData->mStream = NULL; mPriData->mDataSource = NULL; } #endif if (mPriData) { free(mPriData); mPriData = NULL; } logi("AwMetadataRetriever destroyed."); } void AwMetadataRetriever::clear() { //* set mCancelPrepareFlag to force the CdxParserPrepare() quit. //* this can prevend the setDataSource() operation from blocking at a network io. //* but the retriever's setDataSource() method is a synchronize operation, so I think //* this take no effect, because user can not return from setDataSource() to call this //* method if user's thread is blocked at the setDataSource() operation. if(mPriData->mAlbumArtPic != NULL) { delete mPriData->mAlbumArtPic; mPriData->mAlbumArtPic = NULL; } clearHeaders(&mPriData->mHeader); memset(&mPriData->mMediaInfo, 0, sizeof(CdxMediaInfoT)); mPriData->mMetaData->clear(); #if MediaScanDedug mPriData->mFd = -1; #endif return; } #if (CONF_ANDROID_MAJOR_VER >= 5) status_t AwMetadataRetriever::setDataSource(const sp &httpService, const char* pUrl, const KeyedVector* pHeaders) #else status_t AwMetadataRetriever::setDataSource(const char* pUrl, const KeyedVector* pHeaders) #endif { int ret = 0; #if (CONF_ANDROID_MAJOR_VER >= 5) CEDARX_UNUSE(httpService); #endif logd("set data source, url = %s", pUrl); clear(); //* release parser, decoder and other resource for previous file. //* 1. parse pHeaders. ret = parseHeaders(&mPriData->mHeader, (char*)pUrl, (KeyedVector*)pHeaders); if (ret < 0) { loge("parseHeaders failed."); return NO_MEMORY; } //* 2. XRetriever set datasource. ret = XRetrieverSetDataSource(mPriData->mXRetriever, pUrl, mPriData->mHeader); if (ret < 0) { loge("XRetrieverSetDataSource failed."); return UNKNOWN_ERROR; } XRetrieverGetMetaData(mPriData->mXRetriever, METADATA_MEDIAINFO, &mPriData->mMediaInfo); storeMetadata(); return OK; } status_t AwMetadataRetriever::setDataSource(int fd, int64_t nOffset, int64_t nLength) { char str[128]; int ret = 0; clear(); //* release parser, decoder and other resource for previous file. logd("set data source, fd = %d, nLength: %lld", fd, nLength); #if MediaScanDedug mPriData->mFd = fd; #endif //* 1. set the datasource object. sprintf(str, "fd://%d?offset=%ld&length=%lld", fd, (long int)nOffset, (long long)nLength); ret = XRetrieverSetDataSource(mPriData->mXRetriever, str, mPriData->mHeader); if (ret < 0) { loge("XRetrieverSetDataSource failed."); return UNKNOWN_ERROR; } XRetrieverGetMetaData(mPriData->mXRetriever, METADATA_MEDIAINFO, &mPriData->mMediaInfo); storeMetadata(); return OK; } #if (CONF_ANDROID_MAJOR_VER >= 6) #if ((CONF_ANDROID_MAJOR_VER < 8) || \ ((CONF_ANDROID_MAJOR_VER == 8) && (CONF_ANDROID_SUB_VER == 0))) status_t AwMetadataRetriever::setDataSource(const sp &source) #elif ((CONF_ANDROID_MAJOR_VER == 8) && (CONF_ANDROID_SUB_VER > 0)) status_t AwMetadataRetriever::setDataSource(const sp& source, const char *mime) #endif { #if ((CONF_ANDROID_MAJOR_VER == 8) && (CONF_ANDROID_SUB_VER > 0)) CEDARX_UNUSE(mime); #endif int ret = 0; CdxStreamT *stream = MediaDataSourceOpen(source); if(stream == NULL) { loge("awmetadataretriever MediaDataSourceOpen fail!"); return UNKNOWN_ERROR; } mPriData->mDataSource = source; mPriData->mStream = stream; char str[128]; sprintf(str, "datasource://%p",stream); ret = XRetrieverSetDataSource(mPriData->mXRetriever, str, mPriData->mHeader); if (ret < 0) { loge("XRetrieverSetDataSource failed."); return UNKNOWN_ERROR; } XRetrieverGetMetaData(mPriData->mXRetriever, METADATA_MEDIAINFO, &mPriData->mMediaInfo); storeMetadata(); return (status_t)ret; } #endif void AwMetadataRetriever::storeMetadata(void) { int i; char tmp[256]; int nStrLen = 0; String8 mStrData; if(mPriData->mMediaInfo.pAlbumArtBuf != NULL && mPriData->mMediaInfo.nAlbumArtBufSize > 0 && mPriData->mAlbumArtPic == NULL) { #if (CONF_ANDROID_MAJOR_VER >= 5) mPriData->mAlbumArtPic = MediaAlbumArt::fromData(mPriData->mMediaInfo.nAlbumArtBufSize, mPriData->mMediaInfo.pAlbumArtBuf); #else mPriData->mAlbumArtPic = new MediaAlbumArt; mPriData->mAlbumArtPic->mSize = mPriData->mMediaInfo.nAlbumArtBufSize; mPriData->mAlbumArtPic->mData = new uint8_t[mPriData->mMediaInfo.nAlbumArtBufSize]; memcpy(mPriData->mAlbumArtPic->mData, mPriData->mMediaInfo.pAlbumArtBuf, mPriData->mMediaInfo.nAlbumArtBufSize); #endif } #if (CONF_ANDROID_MAJOR_VER >= 5) CharacterEncodingDetector *detector = new CharacterEncodingDetector(); for (int i = 0; i < kNumMapEntries; ++i) { cdx_uint8 *value; if (metafindCStringByKey(&mPriData->mMediaInfo, kMap[i].from, &value)) { if (kMap[i].name) { // add to charset detector detector->addTag(kMap[i].name, (const char*)value); } else { // directly add to output list mPriData->mMetaData->add(kMap[i].to, String8((const char*)value)); } } } detector->detectAndConvert(); int size = detector->size(); logd("detect conventor size : %d", size); if (size) { for (int i = 0; i < size; i++) { const char *name; const char *value; detector->getTag(i, &name, &value); for (int j = 0; j < kNumMapEntries; ++j) { if (kMap[j].name && !strcmp(kMap[j].name, name)) { mPriData->mMetaData->add(kMap[j].to, String8(value)); } } } } delete detector; #else for (int i = 0; i < kNumMapEntries; ++i) { cdx_uint8 *value; if (metafindCStringByKey(&mPriData->mMediaInfo, kMap[i].from, &value)) { mPriData->mMetaData->add(kMap[i].to, String8((const char *)value)); } } #endif //* no information to give the title. //* mp3 file may contain this information in its metadata, index by tag "TYE" or "TYER"; //* mov file may contain this information in its metadata, index by FOURCC "0xa9 'd' 'a' 'y'"; //* /** //* * The metadata key to retrieve the playback duration of the data source. //* */ //* public static final int METADATA_KEY_DURATION = 9; if(mPriData->mMediaInfo.programIndex >= 0 && mPriData->mMediaInfo.programNum >= mPriData->mMediaInfo.programIndex) { //* The duration value is a string representing the duration in ms. sprintf(tmp, "%d", mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].duration); mPriData->mMetaData->add(METADATA_KEY_DURATION, String8(tmp)); logv("duration:%d", mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].duration); } //* /** //* * The metadata key to retrieve the number of tracks, such as audio, video, //* * text, in the data source, such as a mp4 or 3gpp file. //* */ //* public static final int METADATA_KEY_NUM_TRACKS = 10; if(mPriData->mMediaInfo.programIndex >= 0 && mPriData->mMediaInfo.programNum >= mPriData->mMediaInfo.programIndex) { int nTrackCount = mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].videoNum + mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].audioNum + mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].subtitleNum; sprintf(tmp, "%d", nTrackCount); mPriData->mMetaData->add(METADATA_KEY_NUM_TRACKS, String8(tmp)); } //* /** //* * The metadata key to retrieve the information of the writer (such as //* * lyricist) of the data source. //* */ //* public static final int METADATA_KEY_WRITER = 11; #if 0 mPriData->mMetaData->add(METADATA_KEY_WRITER, String8("unknown writer")); //* no information to give the writer. //* ogg file may contain this information in its vorbis comment, index by tag "LYRICIST"; //* mov file may contain this information in its metadata, index by FOURCC "0xa9 'w' 'r' 't'"; #endif //* /** //* * The metadata key to retrieve the mime type of the data source. Some //* * example mime types include: "video/mp4", "audio/mp4", "audio/amr-wb", //* * etc. //* */ //* public static final int METADATA_KEY_MIMETYPE = 12; if(mPriData->mMediaInfo.programIndex >= 0 && mPriData->mMediaInfo.programNum >= mPriData->mMediaInfo.programIndex) { int type = -1; XRetrieverGetMetaData(mPriData->mXRetriever, METADATA_PARSER_TYPE, &type); switch(type) { case CDX_PARSER_MOV: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/mp4")); break; case CDX_PARSER_MKV: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/x-matroska")); break; case CDX_PARSER_ASF: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/x-ms-asf")); break; case CDX_PARSER_MPG: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/mpeg")); break; case CDX_PARSER_TS: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/mp2ts")); break; case CDX_PARSER_AVI: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/avi")); break; case CDX_PARSER_FLV: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/cedarx")); break; case CDX_PARSER_PMP: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/cedarx")); break; case CDX_PARSER_HLS: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("application/vnd.apple.mpegurl")); break; case CDX_PARSER_DASH: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/cedarx")); break; case CDX_PARSER_MMS: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/cedarx")); break; case CDX_PARSER_BD: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/cedarx")); break; case CDX_PARSER_OGG: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("application/ogg")); break; case CDX_PARSER_M3U9: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/cedarx")); break; case CDX_PARSER_RMVB: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/cedarx")); break; case CDX_PARSER_PLAYLIST: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/cedarx")); break; case CDX_PARSER_WAV: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("audio/x-wav")); break; case CDX_PARSER_APE: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("audio/cedara")); break; case CDX_PARSER_MP3: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("audio/mpeg")); break; case CDX_PARSER_WVM: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("application/x-android-drm-fl")); break; case CDX_PARSER_REMUX: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/cedarx")); break; default: break; //* going to be add: //* WAV: audio/x-wav //* APE: //* ... //* Widevine: video/wvm //* ... } #if 0 //* add video mimetype. for(i=0; imMediaInfo.program[mMediaInfo.programIndex].videoNum; i++) { switch(mPriData->mMediaInfo.program[mMediaInfo.programIndex].video[i].eCodecFormat) { case VIDEO_CODEC_FORMAT_MJPEG: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/jpeg")); break; case VIDEO_CODEC_FORMAT_MPEG1: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/mpeg1")); break; case VIDEO_CODEC_FORMAT_MPEG2: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/mpeg2")); break; case VIDEO_CODEC_FORMAT_MPEG4: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/mp4v-es")); break; case VIDEO_CODEC_FORMAT_MSMPEG4V1: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/x-ms-mpeg4v1")); break; case VIDEO_CODEC_FORMAT_MSMPEG4V2: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/x-ms-mpeg4v2")); break; case VIDEO_CODEC_FORMAT_DIVX3: case VIDEO_CODEC_FORMAT_DIVX4: case VIDEO_CODEC_FORMAT_DIVX5: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/divx")); break; case VIDEO_CODEC_FORMAT_XVID: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/xvid")); break; case VIDEO_CODEC_FORMAT_H263: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/3gpp")); break; case VIDEO_CODEC_FORMAT_SORENSSON_H263: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/flv1")); break; case VIDEO_CODEC_FORMAT_RXG2: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/rvg2")); break; case VIDEO_CODEC_FORMAT_WMV1: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/wmv1")); break; case VIDEO_CODEC_FORMAT_WMV2: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/wmv2")); break; case VIDEO_CODEC_FORMAT_WMV3: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/x-ms-wmv")); break; case VIDEO_CODEC_FORMAT_VP6: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/x-vnd.on2.vp6")); break; case VIDEO_CODEC_FORMAT_VP8: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/x-vnd.on2.vp8")); break; case VIDEO_CODEC_FORMAT_VP9: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/x-vnd.on2.vp9")); break; case VIDEO_CODEC_FORMAT_RX: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/realvideo")); break; case VIDEO_CODEC_FORMAT_H264: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/avc")); break; case VIDEO_CODEC_FORMAT_H265: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/hevc")); break; case VIDEO_CODEC_FORMAT_AVS: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("video/avs")); break; default: break; } } #endif #if 1 if(mPriData->mMediaInfo.programIndex >= 0 && mPriData->mMediaInfo.programNum >= mPriData->mMediaInfo.programIndex) { if((mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].audioNum > 0) && (mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].videoNum <= 0)) { //* add audio mimetype. int programIndex = mPriData->mMediaInfo.programIndex; int audioNum = mPriData->mMediaInfo.program[programIndex].audioNum; for(i = 0; i < audioNum; i++) { enum EAUDIOCODECFORMAT eCodecFormat = mPriData->mMediaInfo.program[programIndex].audio[i].eCodecFormat; switch(eCodecFormat) { case AUDIO_CODEC_FORMAT_MP1: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8(MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I)); break; case AUDIO_CODEC_FORMAT_MP2: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8(MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II)); break; case AUDIO_CODEC_FORMAT_MP3: case AUDIO_CODEC_FORMAT_MP3_PRO: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8(MEDIA_MIMETYPE_AUDIO_MPEG)); break; case AUDIO_CODEC_FORMAT_MPEG_AAC_LC: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8(MEDIA_MIMETYPE_AUDIO_AAC_ADTS)); break; case AUDIO_CODEC_FORMAT_AC3: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8(MEDIA_MIMETYPE_AUDIO_AC3)); break; case AUDIO_CODEC_FORMAT_DTS: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("audio/cedara")); break; case AUDIO_CODEC_FORMAT_LPCM_V: case AUDIO_CODEC_FORMAT_LPCM_A: case AUDIO_CODEC_FORMAT_ADPCM: case AUDIO_CODEC_FORMAT_PPCM: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8(MEDIA_MIMETYPE_AUDIO_RAW)); break; case AUDIO_CODEC_FORMAT_PCM: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("audio/cedara")); break; case AUDIO_CODEC_FORMAT_WMA_STANDARD: case AUDIO_CODEC_FORMAT_WMA_LOSS: case AUDIO_CODEC_FORMAT_WMA_PRO: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("audio/x-ms-wma")); break; case AUDIO_CODEC_FORMAT_FLAC: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8(MEDIA_MIMETYPE_AUDIO_FLAC)); break; case AUDIO_CODEC_FORMAT_APE: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("audio/cedara")); break; case AUDIO_CODEC_FORMAT_OGG: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8(MEDIA_MIMETYPE_AUDIO_VORBIS)); break; case AUDIO_CODEC_FORMAT_RAAC: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8(MEDIA_MIMETYPE_AUDIO_AAC_ADTS)); break; case AUDIO_CODEC_FORMAT_COOK: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("audio/cook")); break; case AUDIO_CODEC_FORMAT_SIPR: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("audio/sipr")); break; case AUDIO_CODEC_FORMAT_ATRC: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("audio/atrc")); break; case AUDIO_CODEC_FORMAT_AMR: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8(MEDIA_MIMETYPE_AUDIO_AMR_WB)); break; case AUDIO_CODEC_FORMAT_RA: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("audio/cedara")); break; default: break; } } } } #endif #if 0 //* add subtitle mimetype. for(i=0; imMetaData->add(METADATA_KEY_MIMETYPE, String8("subtitle/x-subrip")); break; case SUBTITLE_CODEC_IDXSUB: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("subtitle/index-subtitle")); break; case SUBTITLE_CODEC_PGS: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("subtitle/bd-subtitle")); break; case SUBTITLE_CODEC_TXT: case SUBTITLE_CODEC_TIMEDTEXT: case SUBTITLE_CODEC_SRT: case SUBTITLE_CODEC_SMI: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("text/3gpp-tt")); break; case SUBTITLE_CODEC_SSA: mPriData->mMetaData->add(METADATA_KEY_MIMETYPE, String8("text/ssa")); break; default: break; } } #endif } //* /** //* * The metadata key to retrieve the information about the performers or //* * artist associated with the data source. //* */ //* public static final int METADATA_KEY_ALBUMARTIST = 13; #if 0 mPriData->mMetaData->add(METADATA_KEY_ALBUMARTIST, String8("unknown album artist")); //* no information to give the artist. //* ogg file may contain this information in its vorbis comment, index by tag "ALBUMARTIST" //* or "ALBUM ARTIST"; //* mp3 file may contain this information in its metadata, index by tag "TPE2" or "TP2"; //* mov file may contain this information in its metadata, index by FOURCC "'a' 'A' 'R' 'T'"; #endif //* /** //* * The metadata key to retrieve the numberic string that describes which //* * part of a set the audio data source comes from. //* */ //* public static final int METADATA_KEY_DISC_NUMBER = 14; #if 0 mPriData->mMetaData->add(METADATA_KEY_DISC_NUMBER, String8("unknown disk number")); //* no information to tell which part of a set the audio data source comes from. //* ogg file may contain this information in its vorbis comment, index by tag "DISCNUMBER"; //* mp3 file may contain this information in its metadata, index by tag "TPA" or "TPOS"; //* mov file may contain this information in its metadata, index by FOURCC "'d' 'i' 's' 'k'"; #endif //* /** //* * The metadata key to retrieve the music album compilation status. //* */ //* public static final int METADATA_KEY_COMPILATION = 15; #if 0 mPriData->mMetaData->add(METADATA_KEY_COMPILATION, String8("unknown compilation")); //* no information to tell which part of a set the audio data source comes from. //* ogg file may contain this information in its vorbis comment, index by tag "COMPILATION"; //* mp3 file may contain this information in its metadata, index by tag "TCP" or "TCMP"; //* mov file may contain this information in its metadata, index by FOURCC "'c' 'p' 'i' 'l'"; #endif //* /** //* * If this key exists the media contains audio content. //* */ //* public static final int METADATA_KEY_HAS_AUDIO = 16; if(mPriData->mMediaInfo.programIndex >= 0 && mPriData->mMediaInfo.programNum >= mPriData->mMediaInfo.programIndex) { //* add HAS_AUDIO info when have audio,or not add //* (reference to StagefrightMetadataRetriever.cpp) if(mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].audioNum > 0) mPriData->mMetaData->add(METADATA_KEY_HAS_AUDIO, String8("yes")); } //* /** //* * If this key exists the media contains video content. //* */ //* public static final int METADATA_KEY_HAS_VIDEO = 17; if(mPriData->mMediaInfo.programIndex >= 0 && mPriData->mMediaInfo.programNum >= mPriData->mMediaInfo.programIndex) { //* add HAS_VIDEO info when hava video, or not add //* (reference to StagefrightMetadataRetriever.cpp) if(mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].videoNum > 0) mPriData->mMetaData->add(METADATA_KEY_HAS_VIDEO, String8("yes")); } //* /** //* * If the media contains video, this key retrieves its width. //* */ //* public static final int METADATA_KEY_VIDEO_WIDTH = 18; if(mPriData->mMediaInfo.programIndex >= 0 && mPriData->mMediaInfo.programNum >= mPriData->mMediaInfo.programIndex) { if(mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].videoNum > 0) { sprintf(tmp, "%d", mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].video[0].nWidth); mPriData->mMetaData->add(METADATA_KEY_VIDEO_WIDTH, String8(tmp)); } } //* /** //* * If the media contains video, this key retrieves its height. //* */ //* public static final int METADATA_KEY_VIDEO_HEIGHT = 19; if(mPriData->mMediaInfo.programIndex >= 0 && mPriData->mMediaInfo.programNum >= mPriData->mMediaInfo.programIndex) { if(mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].videoNum > 0) { sprintf(tmp, "%d", mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].video[0].nHeight); //* add the video height mPriData->mMetaData->add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp)); } } //* /** //* * This key retrieves the average bitrate (in bits/sec), if available. //* */ //* public static final int METADATA_KEY_BITRATE = 20; #if 0 mPriData->mMetaData->add(METADATA_KEY_BITRATE, String8("unknown bitrate")); //* no information to give the average bitrate. #endif //* /** //* * This key retrieves the language code of text tracks, if available. //* * If multiple text tracks present, the return value will look like: //* * "eng:chi" //* * @hide //* */ //* public static final int METADATA_KEY_TIMED_TEXT_LANGUAGES = 21; if(mPriData->mMediaInfo.programIndex >= 0 && mPriData->mMediaInfo.programNum >= mPriData->mMediaInfo.programIndex) { if(mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].subtitleNum > 0) { int len; char buffer[256]; tmp[0] = '\0'; buffer[0] = '\0'; int index = mPriData->mMediaInfo.programIndex; for(i=0; imMediaInfo.program[index].subtitleNum; i++) { if(i != 0) sprintf(buffer, "%s:", tmp); //* add a ":". len = strlen((const char*)mPriData->mMediaInfo.program[index].subtitle[i].strLang); if(len == 0) len = strlen("unknown"); if(len + strlen(tmp) >= (sizeof(tmp)-1)) { logw("can not set the language of subtitle correctly"); break; //* for save. } if(strlen((const char*)mPriData->mMediaInfo.program[index].subtitle[i].strLang) > 0) sprintf(buffer, "%s%s", tmp, mPriData->mMediaInfo.program[index].subtitle[i].strLang); else sprintf(buffer, "%s%s", tmp, "unknown"); } mPriData->mMetaData->add(METADATA_KEY_TIMED_TEXT_LANGUAGES, String8(buffer)); } } //* /** //* * If this key exists the media is drm-protected. //* * @hide //* */ //* public static final int METADATA_KEY_IS_DRM = 22; #if 0 mPriData->mMetaData->add(METADATA_KEY_IS_DRM, String8("0")); //* no information to give the drm info. #endif //* /** //* * This key retrieves the location information, if available. //* * The location should be specified according to ISO-6709 standard, under //* * a mp4/3gp box "@xyz". Location with longitude of -90 degrees and latitude //* * of 180 degrees will be retrieved as "-90.0000+180.0000", for instance. //* */ //* public static final int METADATA_KEY_LOCATION = 23; //* set the location info //* we should not add it when the nStrlen is 0 nStrLen = strlen((const char*)mPriData->mMediaInfo.location); if(nStrLen != 0) mPriData->mMetaData->add(METADATA_KEY_LOCATION, String8((const char*)mPriData->mMediaInfo.location)); //* /** //* * This key retrieves the video rotation angle in degrees, if available. //* * The video rotation angle may be 0, 90, 180, or 270 degrees. //* */ //* public static final int METADATA_KEY_VIDEO_ROTATION = 24; //* set rotation info //* mov parser can get the rotate angle. //* we should not add it when the nStrlen is 0 nStrLen = strlen((const char*)mPriData->mMediaInfo.rotate); if(nStrLen != 0) mPriData->mMetaData->add(METADATA_KEY_VIDEO_ROTATION, String8((const char*)mPriData->mMediaInfo.rotate)); #if (CONF_ANDROID_MAJOR_VER >= 8) //* METADATA_KEY_CAPTURE_FRAMERATE = 25 if(mPriData->mMediaInfo.programIndex >= 0 && mPriData->mMediaInfo.programNum >= mPriData->mMediaInfo.programIndex) { if(mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].videoNum > 0) { if(mPriData->mMediaInfo.androidCaptureFps) { sprintf(tmp, "%f",mPriData->mMediaInfo.androidCaptureFps); //* add the frame rate mPriData->mMetaData->add(METADATA_KEY_CAPTURE_FRAMERATE, String8(tmp)); } else { sprintf(tmp, "%d", mPriData->mMediaInfo.program[mPriData->mMediaInfo.programIndex].video[0].nFrameRate/1000); //* add the frame rate mPriData->mMetaData->add(METADATA_KEY_CAPTURE_FRAMERATE, String8(tmp)); } } } #endif return; } const char* AwMetadataRetriever::extractMetadata(int keyCode) { //* keyCode is defined in "android/framworks/av/include/media/mediametadataretriever.h" and //* "android/frameworks/base/media/java/android/media/mediametadataretriever.java". //* keyCodes list here. //* /** //* * The metadata key to retrieve the numeric string describing the //* * order of the audio data source on its original recording. //* */ //* public static final int METADATA_KEY_CD_TRACK_NUMBER = 0; //* /** //* * The metadata key to retrieve the information about the album title //* * of the data source. //* */ //* public static final int METADATA_KEY_ALBUM = 1; //* /** //* * The metadata key to retrieve the information about the artist of //* * the data source. //* */ //* public static final int METADATA_KEY_ARTIST = 2; //* /** //* * The metadata key to retrieve the information about the author of //* * the data source. //* */ //* public static final int METADATA_KEY_AUTHOR = 3; //* /** //* * The metadata key to retrieve the information about the composer of //* * the data source. //* */ //* public static final int METADATA_KEY_COMPOSER = 4; //* /** //* * The metadata key to retrieve the date when the data source was created //* * or modified. //* */ //* public static final int METADATA_KEY_DATE = 5; //* /** //* * The metadata key to retrieve the content type or genre of the data //* * source. //* */ //* public static final int METADATA_KEY_GENRE = 6; //* /** //* * The metadata key to retrieve the data source title. //* */ //* public static final int METADATA_KEY_TITLE = 7; //* /** //* * The metadata key to retrieve the year when the data source was created //* * or modified. //* */ //* public static final int METADATA_KEY_YEAR = 8; //* /** //* * The metadata key to retrieve the playback duration of the data source. //* */ //* public static final int METADATA_KEY_DURATION = 9; //* /** //* * The metadata key to retrieve the number of tracks, such as audio, video, //* * text, in the data source, such as a mp4 or 3gpp file. //* */ //* public static final int METADATA_KEY_NUM_TRACKS = 10; //* /** //* * The metadata key to retrieve the information of the writer (such as //* * lyricist) of the data source. //* */ //* public static final int METADATA_KEY_WRITER = 11; //* /** //* * The metadata key to retrieve the mime type of the data source. Some //* * example mime types include: "video/mp4", "audio/mp4", "audio/amr-wb", //* * etc. //* */ //* public static final int METADATA_KEY_MIMETYPE = 12; //* /** //* * The metadata key to retrieve the information about the performers or //* * artist associated with the data source. //* */ //* public static final int METADATA_KEY_ALBUMARTIST = 13; //* /** //* * The metadata key to retrieve the numberic string that describes which //* * part of a set the audio data source comes from. //* */ //* public static final int METADATA_KEY_DISC_NUMBER = 14; //* /** //* * The metadata key to retrieve the music album compilation status. //* */ //* public static final int METADATA_KEY_COMPILATION = 15; //* /** //* * If this key exists the media contains audio content. //* */ //* public static final int METADATA_KEY_HAS_AUDIO = 16; //* /** //* * If this key exists the media contains video content. //* */ //* public static final int METADATA_KEY_HAS_VIDEO = 17; //* /** //* * If the media contains video, this key retrieves its width. //* */ //* public static final int METADATA_KEY_VIDEO_WIDTH = 18; //* /** //* * If the media contains video, this key retrieves its height. //* */ //* public static final int METADATA_KEY_VIDEO_HEIGHT = 19; //* /** //* * This key retrieves the average bitrate (in bits/sec), if available. //* */ //* public static final int METADATA_KEY_BITRATE = 20; //* /** //* * This key retrieves the language code of text tracks, if available. //* * If multiple text tracks present, the return value will look like: //* * "eng:chi" //* * @hide //* */ //* public static final int METADATA_KEY_TIMED_TEXT_LANGUAGES = 21; //* /** //* * If this key exists the media is drm-protected. //* * @hide //* */ //* public static final int METADATA_KEY_IS_DRM = 22; //* /** //* * This key retrieves the location information, if available. //* * The location should be specified according to ISO-6709 standard, under //* * a mp4/3gp box "@xyz". Location with longitude of -90 degrees and latitude //* * of 180 degrees will be retrieved as "-90.0000+180.0000", for instance. //* */ //* public static final int METADATA_KEY_LOCATION = 23; //* /** //* * This key retrieves the video rotation angle in degrees, if available. //* * The video rotation angle may be 0, 90, 180, or 270 degrees. //* */ //* public static final int METADATA_KEY_VIDEO_ROTATION = 24; int index; const char* strMetadataName[] = { "CD_TRACK_NUMBER", "ALBUM", "ARTIST", "AUTHOR", "CD_TRACK_COMPOSER", "DATE", "GENRE", "TITLE", "YEAR", "DURATION", "NUM_TRACKS", "WRITER", "MIMETYPE", "ALBUMARTIST", "DISC_NUMBER", "COMPILATION", "HAS_AUDIO", "HAS_VIDEO", "VIDEO_WIDTH", "VIDEO_HEIGHT", "BITRATE", "TIMED_TEXT_LANGUAGES", "IS_DRM", "LOCATION", "VIDEO_ROTATION" }; index = mPriData->mMetaData->indexOfKey(keyCode); if (index < 0) { if(keyCode >=0 && keyCode <= 24) { logw("no metadata for %s.", strMetadataName[keyCode]); } return NULL; } return mPriData->mMetaData->valueAt(index).string(); } MediaAlbumArt* AwMetadataRetriever::extractAlbumArt() { //* no album art picture extracted. //* ogg parser can find the album art picture in its vorbis comment, //* index by tag "METADATA_BLOCK_PICTURE"; //* flac parser can find the album art picture in its meta data; //* mp3 parser can find the album art picture in its id3 data; //* mov parser can find the album art picture in its metadata, //* index by FOURCC "'c' 'o' 'v' 'r'"; if(mPriData->mAlbumArtPic != NULL) { #if (CONF_ANDROID_MAJOR_VER >= 5) return mPriData->mAlbumArtPic->clone(); #else return new MediaAlbumArt(*mPriData->mAlbumArtPic); #endif } else { return NULL; } //* note: //* if it is a media file with drm protection, we should not return an album art picture. } sp AwMetadataRetriever::getStreamAtTime(int64_t timeUs) { sp mem = NULL; XVideoStream *pXVideoStream; uint8_t* pOutBuf; int32_t nBitStreamLength; pXVideoStream = XRetrieverGetStreamAtTime(mPriData->mXRetriever, timeUs); if(pXVideoStream == NULL) { loge("XRetrieverGetStreamAtTime failed."); return NULL; } pOutBuf = pXVideoStream->mBuf; nBitStreamLength = pXVideoStream->mSize; //* copy bitstream to ashmem. if(pOutBuf && nBitStreamLength) { sp heap = new MemoryHeapBase(nBitStreamLength + 4, 0, "awmetadataretriever"); unsigned char* pData = NULL; if (heap == NULL) loge("failed to create MemoryDealer"); mem = new MemoryBase(heap, 0, nBitStreamLength + 4); if (mem == NULL) { loge("not enough memory for stream size = %d", nBitStreamLength); } else { pData = static_cast(mem->pointer()); pData[0] = (nBitStreamLength) & 0xff; pData[1] = (nBitStreamLength>>8) & 0xff; pData[2] = (nBitStreamLength>>16) & 0xff; pData[3] = (nBitStreamLength>>24) & 0xff; memcpy(pData+4, pOutBuf, nBitStreamLength); } } logv("bBitStreamLength: %p,%d", pOutBuf, nBitStreamLength); return mem; } #if ((CONF_ANDROID_MAJOR_VER < 8) || \ ((CONF_ANDROID_MAJOR_VER == 8) && (CONF_ANDROID_SUB_VER == 0))) VideoFrame* AwMetadataRetriever::getFrameAtTime(int64_t timeUs, int option) { VideoFrame* pVideoFrame; XVideoFrame* pXVideoFrame; CEDARX_UNUSE(option); #if MediaScanDedug logd("getFrameAtTime, mFd=%d", mPriData->mFd); #endif pXVideoFrame = XRetrieverGetFrameAtTime(mPriData->mXRetriever, timeUs, option); if(pXVideoFrame == NULL) { loge("XRetrieverGetFrameAtTime failed."); return NULL; } pVideoFrame = new VideoFrame; if(pVideoFrame == NULL) { loge("can not allocate memory for video frame."); return NULL; } pVideoFrame->mDisplayWidth = pXVideoFrame->mDisplayWidth; pVideoFrame->mDisplayHeight = pXVideoFrame->mDisplayHeight; pVideoFrame->mWidth = pXVideoFrame->mWidth; pVideoFrame->mHeight = pXVideoFrame->mHeight; pVideoFrame->mSize = pXVideoFrame->mSize; pVideoFrame->mRotationAngle = pXVideoFrame->mRotationAngle; pVideoFrame->mData = new unsigned char[pVideoFrame->mSize]; if(pVideoFrame->mData == NULL) { loge("can not allocate memory for video frame."); delete pVideoFrame; return NULL; } memcpy(pVideoFrame->mData, pXVideoFrame->mData, pXVideoFrame->mSize); return pVideoFrame; } #else VideoFrame* AwMetadataRetriever::getFrameAtTime(int64_t timeUs, int option, int colorFormat, bool metaOnly) { int bpp; XVideoFrame* pXVideoFrame; CEDARX_UNUSE(option); if(metaOnly == true) { logd("==== metaOnly is true, cannot support"); return NULL; } switch (colorFormat) { case HAL_PIXEL_FORMAT_RGB_565: { bpp = 2; break; } case HAL_PIXEL_FORMAT_RGBA_8888: case HAL_PIXEL_FORMAT_BGRA_8888: { loge("Unsupported color format: %d", colorFormat); bpp = 4; return NULL; } default: { loge("Unsupported color format: %d", colorFormat); return NULL; } } pXVideoFrame = XRetrieverGetFrameAtTime(mPriData->mXRetriever, timeUs, option); if(pXVideoFrame == NULL) { loge("XRetrieverGetFrameAtTime failed."); return NULL; } VideoFrame* pVideoFrame = new VideoFrame(pXVideoFrame->mWidth, pXVideoFrame->mHeight, pXVideoFrame->mDisplayWidth, pXVideoFrame->mDisplayHeight, pXVideoFrame->mRotationAngle, bpp, !metaOnly, NULL/*iccData*/, 0/*iccSize*/); pVideoFrame->mData = new unsigned char[pVideoFrame->mSize]; if(pVideoFrame->mData == NULL) { loge("can not allocate memory for video frame."); delete pVideoFrame; return NULL; } memcpy(pVideoFrame->mData, pXVideoFrame->mData, pXVideoFrame->mSize); return pVideoFrame; } #endif static int parseHeaders(CdxKeyedVectorT **header, char *uri, KeyedVector* pHeaders) { int nHeaderSize; int i; clearHeaders(header); if(uri != NULL) { if(pHeaders != NULL && (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8))) { //* remove "x-hide-urls-from-log" ? nHeaderSize = pHeaders->size(); if (nHeaderSize <= 0) return -1; *header = CdxKeyedVectorCreate(nHeaderSize); if (*header == NULL) { logw("CdxKeyedVectorCreate() failed"); return -1; } String8 key; String8 value; for (i = 0; i < nHeaderSize; i++) { key = pHeaders->keyAt(i); value = pHeaders->valueAt(i); if (CdxKeyedVectorAdd(*header, key.string(), value.string()) != 0) { clearHeaders(header); return -1; } } } } return 0; } static void clearHeaders(CdxKeyedVectorT **header) { if (*header != NULL) { CdxKeyedVectorDestroy(*header); *header = NULL; } return; } static int64_t GetSysTime() { int64_t time; struct timeval t; gettimeofday(&t, NULL); time = (int64_t)t.tv_sec * 1000000; time += t.tv_usec; return time; } static int metafindCStringByKey(CdxMediaInfoT* mediaInfo, int key, cdx_uint8** value) { int strsz = 0; switch(key) { case kKeyAlbum: logd("get kKeyAlbum"); *value = mediaInfo->album; strsz = mediaInfo->albumsz; break; case kKeyArtist: logd("get kKeyArtist"); *value = mediaInfo->artist; strsz = mediaInfo->artistsz; break; case kKeyAlbumArtist: logd("get kKeyAlbumArtist"); *value = mediaInfo->albumArtist; strsz = mediaInfo->albumArtistsz; break; case kKeyAuthor: logd("get kKeyAuthor"); *value = mediaInfo->author; strsz = mediaInfo->authorsz; break; case kKeyComposer: logd("get kKeyComposer"); *value = mediaInfo->composer; strsz = mediaInfo->composersz; break; case kKeyDate: logd("get kKeyDate"); *value = mediaInfo->date; strsz = mediaInfo->datesz; break; case kKeyGenre: logd("get kKeyGenre"); *value = mediaInfo->genre; strsz = mediaInfo->genresz; break; case kKeyTitle: logd("get kKeyTitle"); *value = mediaInfo->title; strsz = mediaInfo->titlesz; break; case kKeyYear: logd("get kKeyYear"); *value = mediaInfo->year; strsz = mediaInfo->yearsz; break; case kKeyWriter: logd("get kKeyWriter"); *value = mediaInfo->writer; strsz = mediaInfo->writersz; break; case kKeyCompilation: logd("get kKeyCompilation"); *value = mediaInfo->compilation; strsz = mediaInfo->compilationsz; break; case kKeyCDTrackNumber: logd("get kKeyCDTrackNumber"); *value = mediaInfo->cdTrackNumber; strsz = mediaInfo->cdTrackNumbersz; break; default: logd("get null"); *value = NULL; strsz = 0; break; } return strsz; }