SmartAudio/package/allwinner/tina_multimedia/libcedarx/android_adapter/awplayer/subtitleUtils.cpp

400 lines
12 KiB
C++
Executable File

/*
* Copyright (c) 2008-2016 Allwinner Technology Co. Ltd.
* All rights reserved.
*
* File : subtitleUtils.cpp
* Description : subtitle util function, including charset convert
* History :
* Author : AL3
* Date : 2015/05/05
* Comment : create first version
*
*/
#include "subtitleUtils.h"
#include "media/mediaplayerinfo.h"
#include "unicode/ucnv.h"
#include "unicode/ustring.h"
#include "cdx_log.h"
namespace android {
//* the CHARSET_XXX strings is defined in "av/include/media/mediaplayerinfo.h",
//* and it should be the same as strings defined in "base/media/java/android/media/MediaPlayer.java"
const char* strTextCodecFormats[] =
{
CHARSET_UNKNOWN ,
CHARSET_BIG5 ,
CHARSET_BIG5_HKSCS ,
CHARSET_BOCU_1 ,
CHARSET_CESU_8 ,
CHARSET_CP864 ,
CHARSET_EUC_JP ,
CHARSET_EUC_KR ,
CHARSET_GB18030 ,
CHARSET_GBK ,
CHARSET_HZ_GB_2312 ,
CHARSET_ISO_2022_CN ,
CHARSET_ISO_2022_CN_EXT ,
CHARSET_ISO_2022_JP ,
CHARSET_ISO_2022_KR ,
CHARSET_ISO_8859_1 ,
CHARSET_ISO_8859_10 ,
CHARSET_ISO_8859_13 ,
CHARSET_ISO_8859_14 ,
CHARSET_ISO_8859_15 ,
CHARSET_ISO_8859_16 ,
CHARSET_ISO_8859_2 ,
CHARSET_ISO_8859_3 ,
CHARSET_ISO_8859_4 ,
CHARSET_ISO_8859_5 ,
CHARSET_ISO_8859_6 ,
CHARSET_ISO_8859_7 ,
CHARSET_ISO_8859_8 ,
CHARSET_ISO_8859_9 ,
CHARSET_KOI8_R ,
CHARSET_KOI8_U ,
CHARSET_MACINTOSH ,
CHARSET_SCSU ,
CHARSET_SHIFT_JIS ,
CHARSET_TIS_620 ,
CHARSET_US_ASCII ,
CHARSET_UTF_16 ,
CHARSET_UTF_16BE ,
CHARSET_UTF_16LE ,
CHARSET_UTF_32 ,
CHARSET_UTF_32BE ,
CHARSET_UTF_32LE ,
CHARSET_UTF_7 ,
CHARSET_UTF_8 ,
CHARSET_WINDOWS_1250 ,
CHARSET_WINDOWS_1251 ,
CHARSET_WINDOWS_1252 ,
CHARSET_WINDOWS_1253 ,
CHARSET_WINDOWS_1254 ,
CHARSET_WINDOWS_1255 ,
CHARSET_WINDOWS_1256 ,
CHARSET_WINDOWS_1257 ,
CHARSET_WINDOWS_1258 ,
CHARSET_X_DOCOMO_SHIFT_JIS_2007 ,
CHARSET_X_GSM_03_38_2000 ,
CHARSET_X_IBM_1383_P110_1999 ,
CHARSET_X_IMAP_MAILBOX_NAME ,
CHARSET_X_ISCII_BE ,
CHARSET_X_ISCII_DE ,
CHARSET_X_ISCII_GU ,
CHARSET_X_ISCII_KA ,
CHARSET_X_ISCII_MA ,
CHARSET_X_ISCII_OR ,
CHARSET_X_ISCII_PA ,
CHARSET_X_ISCII_TA ,
CHARSET_X_ISCII_TE ,
CHARSET_X_ISO_8859_11_2001 ,
CHARSET_X_JAVAUNICODE ,
CHARSET_X_KDDI_SHIFT_JIS_2007 ,
CHARSET_X_MAC_CYRILLIC ,
CHARSET_X_SOFTBANK_SHIFT_JIS_2007 ,
CHARSET_X_UNICODEBIG ,
CHARSET_X_UTF_16LE_BOM ,
CHARSET_X_UTF16_OPPOSITEENDIAN ,
CHARSET_X_UTF16_PLATFORMENDIAN ,
CHARSET_X_UTF32_OPPOSITEENDIAN ,
CHARSET_X_UTF32_PLATFORMENDIAN ,
NULL
};
static int SubtitleUtilsConvertUnicode(char* pOutBuf,
int nOutBufSize,
SubtitleItem* pSubItem,
const char* pDefaultTextFormatName)
{
const char *pInBuf = pSubItem->pText;
ESubtitleTextFormat eInputTextFormat = pSubItem->eTextFormat;
int len = pSubItem->nTextLength;
int charset;
const char* enc;;
unsigned int subTextLen;
UErrorCode status;
UConverter* conv;
UConverter* utf8Conv;
const char* src;
int targetLength;
char* target;
//*if subtitle decoder know charset,use it ,or use app's setting.
switch(eInputTextFormat)
{
case SUBTITLE_TEXT_FORMAT_UTF8:
enc = CHARSET_UTF_8;
break;
case SUBTITLE_TEXT_FORMAT_GB2312:
enc = CHARSET_HZ_GB_2312;
break;
case SUBTITLE_TEXT_FORMAT_UTF16LE:
enc = CHARSET_UTF_16LE;
break;
case SUBTITLE_TEXT_FORMAT_UTF16BE:
enc = CHARSET_UTF_16BE;
break;
case SUBTITLE_TEXT_FORMAT_UTF32LE:
enc = CHARSET_UTF_32LE;
break;
case SUBTITLE_TEXT_FORMAT_UTF32BE:
enc = CHARSET_UTF_32BE;
break;
case SUBTITLE_TEXT_FORMAT_BIG5:
enc = CHARSET_BIG5;
break;
case SUBTITLE_TEXT_FORMAT_GBK:
enc = CHARSET_GBK;
break;
case SUBTITLE_TEXT_FORMAT_ANSI: //can not match,set to "UTF-8"
enc = CHARSET_UTF_8;
break;
default:
enc = pDefaultTextFormatName;
break;
}
status = U_ZERO_ERROR;
conv = ucnv_open(enc, &status);
if(U_FAILURE(status))
{
logw("could not create UConverter for %s\n", enc);
memset(pOutBuf, 0, nOutBufSize);
return -1;
}
utf8Conv = ucnv_open("UTF-8", &status);
if (U_FAILURE(status))
{
logw("could not create UConverter for UTF-8\n");
memset(pOutBuf, 0, nOutBufSize);
ucnv_close(conv);
return -1;
}
//*first we need to untangle the utf8 and convert it back to the original bytes
// since we are reducing the length of the string, we can do this in place
src = pInBuf;
targetLength = len * 3 + 1;
//*now convert from native encoding to UTF-8
if(targetLength > nOutBufSize)
targetLength = nOutBufSize;
memset(pOutBuf, 0, nOutBufSize);
target = &pOutBuf[0];
ucnv_convertEx(utf8Conv,
conv,
&target,
(const char*)target + targetLength,
&src,
(const char*)src + len,
NULL,
NULL,
NULL,
NULL,
true,
true,
&status);
if (U_FAILURE(status))
{
logw("ucnv_convertEx failed: %d\n", status);
memset(pOutBuf, 0, nOutBufSize);
}
subTextLen = target - (char*)pOutBuf;
logv("CedarXTimedText::convertUniCode src = %s, target = %s\n, subTextLen = %d",
pInBuf, pOutBuf, subTextLen);
ucnv_close(conv);
ucnv_close(utf8Conv);
return OK;
}
// Store the timing and text sample in a Parcel.
// The Parcel will be sent to MediaPlayer.java through event, and will be
// parsed in TimedText.java.
int SubtitleUtilsFillTextSubtitleToParcel(Parcel* parcelDst,
SubtitleItem* pSubItem,
int nSubtitleID,
const char* strDefaultTextFormatName,
int* mIsFistItem)
{
int nFontStyleIdx;
int nSubStyleFlag;
unsigned int nTextLen;
int nPts;
#define MAX_OUTPUT_TEXT_SIZE (1024)
char strOutText[MAX_OUTPUT_TEXT_SIZE];
SubtitleUtilsConvertUnicode(strOutText,
MAX_OUTPUT_TEXT_SIZE,
pSubItem,
strDefaultTextFormatName);
nFontStyleIdx = 0;
nSubStyleFlag = 0;
nTextLen = strlen((char*)strOutText);
parcelDst->writeInt32(KEY_LOCAL_SETTING);
parcelDst->writeInt32(KEY_START_TIME);
//* pts in unit of us, write out pts in unit of ms.
parcelDst->writeInt32((int)(pSubItem->nPts/1000));
parcelDst->writeInt32(KEY_STRUCT_TEXT);
parcelDst->writeInt32(nTextLen); //* write the size of the text sample
parcelDst->writeInt32(nTextLen); //* write the text sample as a byte array
parcelDst->write((char*)strOutText, nTextLen);
//*set subtitleID
parcelDst->writeInt32(KEY_SUBTITLE_ID);
parcelDst->writeInt32(nSubtitleID);
if(pSubItem->eAlignment != 0)
{
parcelDst->writeInt32(KEY_STRUCT_AWEXTEND_SUBDISPPOS);
//*write text subtitle's position area.
parcelDst->writeInt32(pSubItem->eAlignment);
parcelDst->writeInt32(KEY_STRUCT_AWEXTEND_SCREENRECT);
//*write text subtitle's whole screen rect.
parcelDst->writeInt32(0);
parcelDst->writeInt32(0);
parcelDst->writeInt32(pSubItem->nReferenceVideoHeight);
parcelDst->writeInt32(pSubItem->nReferenceVideoWidth);
if(*mIsFistItem == 1)
{
parcelDst->writeInt32(KEY_STRUCT_TEXT_POS);
//*write text subtitle's position Rect.
parcelDst->writeInt32(pSubItem->nStartY);
parcelDst->writeInt32(pSubItem->nStartX);
parcelDst->writeInt32(pSubItem->nEndY);
parcelDst->writeInt32(pSubItem->nEndX);
*mIsFistItem = 0;
}
}
if(pSubItem->nFontSize!=0 && pSubItem->nPrimaryColor!=0)
{
//*convert strFontName,bBold,bItalic,bUnderlined
if(!strcmp(pSubItem->strFontName, SUBTITLE_FONT_NAME_EPILOG))
nFontStyleIdx = 0;
else if(!strcmp(pSubItem->strFontName, SUBTITLE_FONT_NAME_VERDANA))
nFontStyleIdx = 1;
else if(!strcmp(pSubItem->strFontName, SUBTITLE_FONT_NAME_GEORGIA))
nFontStyleIdx = 2;
else if(!strcmp(pSubItem->strFontName, SUBTITLE_FONT_NAME_ARIAL))
nFontStyleIdx = 3;
else if(!strcmp(pSubItem->strFontName, SUBTITLE_FONT_NAME_TIMES_NEW_ROMAN))
nFontStyleIdx = 4;
else
nFontStyleIdx = -1;
//* In the absence of any bits set in flags, the text
//* is plain. Otherwise, 1: bold, 2: italic, 4: underline
if(pSubItem->bBold)
nSubStyleFlag |= 1<<0;
if(pSubItem->bItalic)
nSubStyleFlag |= 1<<1;
if(pSubItem->bUnderlined)
nSubStyleFlag |= 1<<2;
parcelDst->writeInt32(KEY_STRUCT_STYLE_LIST);
parcelDst->writeInt32(KEY_FONT_ID);
parcelDst->writeInt32(nFontStyleIdx);
parcelDst->writeInt32(KEY_FONT_SIZE);
parcelDst->writeInt32((int)pSubItem->nFontSize);
parcelDst->writeInt32(KEY_TEXT_COLOR_RGBA);
parcelDst->writeInt32((int)pSubItem->nPrimaryColor);
parcelDst->writeInt32(KEY_STYLE_FLAGS);
parcelDst->writeInt32(nSubStyleFlag);
}
return 0;
}
// Store the timing and text sample in a Parcel.
// The Parcel will be sent to MediaPlayer.java through event, and will be
// parsed in TimedText.java.
int SubtitleUtilsFillBitmapSubtitleToParcel(Parcel* parcelDst,
SubtitleItem* pSubItem, int nSubtitleID)
{
int nBufSize;
parcelDst->writeInt32(KEY_LOCAL_SETTING);
parcelDst->writeInt32(KEY_START_TIME);
//* pts in unit of us, write out pts in unit of ms.
parcelDst->writeInt32((int)(pSubItem->nPts/1000));
parcelDst->writeInt32(KEY_STRUCT_AWEXTEND_BMP);
//* write the pixel format of bmp subtitle
parcelDst->writeInt32(KEY_STRUCT_AWEXTEND_PIXEL_FORMAT);
#if 0
parcelDst->writeInt32(pSubItem->ePixelFormat); //* 0: ARGB, 1: YUV, defined in sdecoder.h
//* but currently only support ARGB.
#else
//* application only support PIXEL_FORMAT_RGBA_8888 pixel format, this value will be ignored
//* at frameworks/base/media/java/android/media/TimeText.java::parseParcel().
//* so we write zero here.
if(pSubItem->ePixelFormat != SUBTITLE_PIXEL_FORMAT_ARGB)
{
loge("subtitle pixel format is not ARGB, can not handle.");
abort();
}
parcelDst->writeInt32(0);
#endif
//* write the width of bmp subtitle
parcelDst->writeInt32(KEY_STRUCT_AWEXTEND_PICWIDTH);
parcelDst->writeInt32(pSubItem->nBitmapWidth);
//* write the height of bmp subtitle
parcelDst->writeInt32(KEY_STRUCT_AWEXTEND_PICHEIGHT);
parcelDst->writeInt32(pSubItem->nBitmapHeight);
//* write the reference video width of bmp subtitle
parcelDst->writeInt32(KEY_STRUCT_AWEXTEND_REFERENCE_VIDEO_WIDTH);
parcelDst->writeInt32(pSubItem->nReferenceVideoWidth);
//* write the reference video height of bmp subtitle
parcelDst->writeInt32(KEY_STRUCT_AWEXTEND_REFERENCE_VIDEO_HEIGHT);
parcelDst->writeInt32(pSubItem->nReferenceVideoHeight);
//* write the size of the text sample, we only process PIXEL_FORMAT_RGBA_8888 format currently.
nBufSize = pSubItem->nBitmapWidth*pSubItem->nBitmapHeight*4;
parcelDst->writeInt32(nBufSize);
//* write the argb buffer as an int32_t array
parcelDst->writeInt32(nBufSize/4);
parcelDst->write(pSubItem->pBitmapData, nBufSize);
//* set subtitleID
parcelDst->writeInt32(KEY_SUBTITLE_ID);
parcelDst->writeInt32(nSubtitleID);
return 0;
}
};