SmartAudio/package/allwinner/tina_multimedia/libcedarx/android_adapter/metadataretriever/awmetadataretriever.cpp

1456 lines
54 KiB
C++
Executable File

/*
* 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 <AwPluginManager.h>
#include <stdio.h>
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
#include <private/media/VideoFrame.h>
#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 <cutils/properties.h>
//#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 <iniparserapi.h>
#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<int, String8>* mMetaData;
#if MediaScanDedug
int mFd;
#endif
XRetriever *mXRetriever;
CdxKeyedVectorT *mHeader;
#if (CONF_ANDROID_MAJOR_VER >= 6)
sp<DataSource> mDataSource;
CdxStreamT* mStream;
#endif
}MetadataPriData;
static int parseHeaders(CdxKeyedVectorT **header, char *uri,
KeyedVector<String8, String8>* 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<int, String8>();
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<IMediaHTTPService> &httpService,
const char* pUrl, const KeyedVector<String8, String8>* pHeaders)
#else
status_t AwMetadataRetriever::setDataSource(const char* pUrl,
const KeyedVector<String8, String8>* 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<String8, String8>*)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<DataSource> &source)
#elif ((CONF_ANDROID_MAJOR_VER == 8) && (CONF_ANDROID_SUB_VER > 0))
status_t AwMetadataRetriever::setDataSource(const sp<DataSource>& 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; i<mPriData->mMediaInfo.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; i<mMediaInfo.program[mMediaInfo.programIndex].subtitleNum; i++)
{
switch(mMediaInfo.program[mMediaInfo.programIndex].subtitle[i].eCodecFormat)
{
case SUBTITLE_CODEC_DVDSUB:
mPriData->mMetaData->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; i<mPriData->mMediaInfo.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<IMemory> AwMetadataRetriever::getStreamAtTime(int64_t timeUs)
{
sp<IMemory> 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<MemoryHeapBase> 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<unsigned char*>(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<String8, String8>* 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;
}