bool CDVDAudioCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) { m_hints = hints; CLog::Log(LOGDEBUG, "CDVDAudioCodecAndroidMediaCodec::Open codec(%d), profile(%d), tag(%d), extrasize(%d)", hints.codec, hints.profile, hints.codec_tag, hints.extrasize); switch(m_hints.codec) { case AV_CODEC_ID_AAC: case AV_CODEC_ID_AAC_LATM: if (!m_hints.extrasize) { //TODO Support adts return false; } m_mime = "audio/mp4a-latm"; m_formatname = "amc-aac"; break; case AV_CODEC_ID_MP2: m_mime = "audio/mpeg-L2"; m_formatname = "amc-mp2"; break; case AV_CODEC_ID_MP3: m_mime = "audio/mpeg"; m_formatname = "amc-mp3"; break; case AV_CODEC_ID_VORBIS: m_mime = "audio/vorbis"; m_formatname = "amc-ogg"; //TODO return false; break; case AV_CODEC_ID_WMAPRO: m_mime = "audio/wmapro"; m_formatname = "amc-wma"; //TODO return false; break; case AV_CODEC_ID_WMAV1: case AV_CODEC_ID_WMAV2: m_mime = "audio/x-ms-wma"; m_formatname = "amc-wma"; //TODO return false; break; case AV_CODEC_ID_AC3: m_mime = "audio/ac3"; m_formatname = "amc-ac3"; break; case AV_CODEC_ID_EAC3: m_mime = "audio/eac3"; m_formatname = "amc-eac3"; break; default: CLog::Log(LOGNOTICE, "CDVDAudioCodecAndroidMediaCodec:: Unknown hints.codec(%d)", hints.codec); return false; break; } m_codec = std::shared_ptr<CJNIMediaCodec>(new CJNIMediaCodec(CJNIMediaCodec::createDecoderByType(m_mime))); if (xbmc_jnienv()->ExceptionCheck()) { // Unsupported type? xbmc_jnienv()->ExceptionClear(); m_codec = NULL; } if (!m_codec) { CLog::Log(LOGERROR, "CDVDAudioCodecAndroidMediaCodec:: Failed to create Android MediaCodec"); return false; } if (!ConfigureMediaCodec()) { m_codec.reset(); return false; } CLog::Log(LOGINFO, "CDVDAudioCodecAndroidMediaCodec:: " "Open Android MediaCodec %s", m_codecname.c_str()); m_opened = true; memset(&m_demux_pkt, 0, sizeof(m_demux_pkt)); return m_opened; }
bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) { // check for 4.1 Jellybean and above. if (CAndroidFeatures::GetVersion() < 16) return false; // mediacodec crashes with null size. Trap this... if (!hints.width || !hints.height) { CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::Open - %s\n", "null size, cannot handle"); return false; } m_drop = false; m_hints = hints; switch(m_hints.codec) { case AV_CODEC_ID_MPEG2VIDEO: m_mime = "video/mpeg2"; m_formatname = "amc-mpeg2"; break; case AV_CODEC_ID_MPEG4: m_mime = "video/mp4v-es"; m_formatname = "amc-mpeg4"; break; case AV_CODEC_ID_H263: m_mime = "video/3gpp"; m_formatname = "amc-h263"; break; case AV_CODEC_ID_VP3: case AV_CODEC_ID_VP6: case AV_CODEC_ID_VP6F: case AV_CODEC_ID_VP8: //m_mime = "video/x-vp6"; //m_mime = "video/x-vp7"; m_mime = "video/x-vnd.on2.vp8"; m_formatname = "amc-vpX"; break; case AV_CODEC_ID_AVS: case AV_CODEC_ID_CAVS: case AV_CODEC_ID_H264: m_mime = "video/avc"; m_formatname = "amc-h264"; // check for h264-avcC and convert to h264-annex-b if (m_hints.extradata && *(uint8_t*)m_hints.extradata == 1) { m_bitstream = new CBitstreamConverter; if (!m_bitstream->Open(m_hints.codec, (uint8_t*)m_hints.extradata, m_hints.extrasize, true)) { SAFE_DELETE(m_bitstream); return false; } } break; case AV_CODEC_ID_VC1: case AV_CODEC_ID_WMV3: m_mime = "video/wvc1"; //m_mime = "video/wmv9"; m_formatname = "amc-vc1"; break; default: CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec:: Unknown hints.codec(%d)", hints.codec); return false; break; } // CJNIMediaCodec::createDecoderByXXX doesn't handle errors nicely, // it crashes if the codec isn't found. This is fixed in latest AOSP, // but not in current 4.1 devices. So 1st search for a matching codec, then create it. m_colorFormat = -1; int num_codecs = CJNIMediaCodecList::getCodecCount(); for (int i = 0; i < num_codecs; i++) { CJNIMediaCodecInfo codec_info = CJNIMediaCodecList::getCodecInfoAt(i); if (codec_info.isEncoder()) continue; m_codecname = codec_info.getName(); if (IsBlacklisted(m_codecname)) continue; CJNIMediaCodecInfoCodecCapabilities codec_caps = codec_info.getCapabilitiesForType(m_mime); if (xbmc_jnienv()->ExceptionOccurred()) { // Unsupported type? xbmc_jnienv()->ExceptionClear(); continue; } std::vector<int> color_formats = codec_caps.colorFormats(); std::vector<std::string> types = codec_info.getSupportedTypes(); // return the 1st one we find, that one is typically 'the best' for (size_t j = 0; j < types.size(); ++j) { if (types[j] == m_mime) { m_codec = boost::shared_ptr<CJNIMediaCodec>(new CJNIMediaCodec(CJNIMediaCodec::createByCodecName(m_codecname))); // clear any jni exceptions, jni gets upset if we do not. if (xbmc_jnienv()->ExceptionOccurred()) { CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::Open ExceptionOccurred"); xbmc_jnienv()->ExceptionClear(); m_codec.reset(); continue; } for (size_t k = 0; k < color_formats.size(); ++k) { CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::Open " "m_codecname(%s), colorFormat(%d)", m_codecname.c_str(), color_formats[k]); if (IsSupportedColorFormat(color_formats[k])) m_colorFormat = color_formats[k]; // Save color format for initial output configuration } break; } } if (m_codec) break; } if (!m_codec) { CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec:: Failed to create Android MediaCodec"); SAFE_DELETE(m_bitstream); return false; } // blacklist of devices that cannot surface render. m_render_sw = CanSurfaceRenderBlackList(m_codecname) || g_advancedSettings.m_mediacodecForceSoftwareRendring; if (m_render_sw) { if (m_colorFormat == -1) { CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec:: No supported color format"); m_codec.reset(); SAFE_DELETE(m_bitstream); return false; } } // setup a YUV420P DVDVideoPicture buffer. // first make sure all properties are reset. memset(&m_videobuffer, 0x00, sizeof(DVDVideoPicture)); m_videobuffer.dts = DVD_NOPTS_VALUE; m_videobuffer.pts = DVD_NOPTS_VALUE; m_videobuffer.color_range = 0; m_videobuffer.color_matrix = 4; m_videobuffer.iFlags = DVP_FLAG_ALLOCATED; m_videobuffer.iWidth = m_hints.width; m_videobuffer.iHeight = m_hints.height; // these will get reset to crop values later m_videobuffer.iDisplayWidth = m_hints.width; m_videobuffer.iDisplayHeight = m_hints.height; if (!ConfigureMediaCodec()) { m_codec.reset(); SAFE_DELETE(m_bitstream); return false; } CLog::Log(LOGINFO, "CDVDVideoCodecAndroidMediaCodec:: " "Open Android MediaCodec %s", m_codecname.c_str()); m_opened = true; return m_opened; }