C++程序  |  193行  |  6.14 KB

/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "tunertvinput_jni.h"
#include <map>

#include "DvbManager.h"
#define LOG_TAG "tunertvinput_jni"
#include "logging.h"

//-------------------------------------------------------------------------------
// JNI native method implementation
//-------------------------------------------------------------------------------

#define TS_PACKET_SIZE 188
#define TS_PAYLOAD_SIZE (TS_PACKET_SIZE * 7) // Fit Ethernet MTU (1500)
#define READ_TIMEOUT_MS 100

static int sTotalBytesFetched = 0;
static std::map<jlong, DvbManager *> sDvbManagers;

/*
 * Class:     com_android_tv_tuner_TunerHal
 * Method:    nativeFinalize
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_com_android_tv_tuner_TunerHal_nativeFinalize(
    JNIEnv *, jobject, jlong deviceId) {
  std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
  if (it != sDvbManagers.end()) {
    delete it->second;
    sDvbManagers.erase(it);
  }
}

/*
 * Class:     com_android_tv_tuner_TunerHal
 * Method:    nativeTune
 * Signature: (JILjava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_android_tv_tuner_TunerHal_nativeTune(
    JNIEnv *env, jobject thiz, jlong deviceId, jint frequency,
    jstring modulation, jint timeout_ms) {
  std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
  DvbManager *dvbManager;
  if (it == sDvbManagers.end()) {
    dvbManager = new DvbManager(env, thiz);
    sDvbManagers.insert(std::pair<jlong, DvbManager *>(deviceId, dvbManager));
  } else {
    dvbManager = it->second;
  }
  int res = dvbManager->tune(env, thiz, frequency,
                             env->GetStringUTFChars(modulation, 0), timeout_ms);
  return (res == 0);
}

/*
 * Class:     com_android_tv_tuner_TunerHal
 * Method:    nativeCloseAllPidFilters
 * Signature: (J)V
 */
JNIEXPORT void JNICALL
Java_com_android_tv_tuner_TunerHal_nativeCloseAllPidFilters(JNIEnv *, jobject,
                                                            jlong deviceId) {
  std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
  if (it != sDvbManagers.end()) {
    it->second->closeAllDvbPidFilter();
  }
}

/*
 * Class:     com_android_tv_tuner_TunerHal
 * Method:    nativeStopTune
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_com_android_tv_tuner_TunerHal_nativeStopTune(
    JNIEnv *, jobject, jlong deviceId) {
  std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
  if (it != sDvbManagers.end()) {
    it->second->stopTune();
  }
}

/*
 * Class:     com_android_tv_tuner_TunerHal
 * Method:    nativeGetSignalStrength
 * Signature: (J)V
 */
JNIEXPORT int JNICALL
Java_com_android_tv_tuner_TunerHal_nativeGetSignalStrength(
    JNIEnv *, jobject, jlong deviceId) {
  std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
  if (it != sDvbManagers.end()) {
    return it->second->getSignalStrength();
  }
  // If DvbManager can't be found,
  // return -3 as signal strength not supported.
  return -3;
}

/*
 * Class:     com_android_tv_tuner_TunerHal
 * Method:    nativeAddPidFilter
 * Signature: (JII)V
 */
JNIEXPORT void JNICALL Java_com_android_tv_tuner_TunerHal_nativeAddPidFilter(
    JNIEnv *env, jobject thiz, jlong deviceId, jint pid, jint filterType) {
  std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
  if (it != sDvbManagers.end()) {
    it->second->startTsPidFilter(env, thiz, pid, filterType);
  }
}

/*
 * Class:     com_android_tv_tuner_TunerHal
 * Method:    nativeWriteInBuffer
 * Signature: (J[BI)I
 */
JNIEXPORT jint JNICALL Java_com_android_tv_tuner_TunerHal_nativeWriteInBuffer(
    JNIEnv *env, jobject thiz, jlong deviceId, jbyteArray javaBuffer,
    jint javaBufferSize) {
  uint8_t tsBuffer[TS_PAYLOAD_SIZE];
  std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
  if (it == sDvbManagers.end()) {
    return -1;
  }
  DvbManager *dvbManager = it->second;

  // Always read multiple of TS_PACKET_SIZE
  javaBufferSize = (javaBufferSize / TS_PACKET_SIZE) * TS_PACKET_SIZE;
  int readBufferSize =
      (javaBufferSize < TS_PAYLOAD_SIZE) ? javaBufferSize : TS_PAYLOAD_SIZE;

  int dataSize = dvbManager->readTsStream(env, thiz, tsBuffer, readBufferSize,
                                          READ_TIMEOUT_MS);
  if (dataSize == 0) {
    ALOGD("No data to read DVR");
    return 0;
  } else if (dataSize < 0) {
    return -1;
  }

  sTotalBytesFetched += dataSize;

  env->SetByteArrayRegion(javaBuffer, 0, dataSize, (jbyte *)tsBuffer);
  return dataSize;
}

/*
 * Class:     com_android_tv_tuner_TunerHal
 * Method:    nativeSetHasPendingTune
 * Signature: (JZ)V
 */
JNIEXPORT void JNICALL
Java_com_android_tv_tuner_TunerHal_nativeSetHasPendingTune(
    JNIEnv *, jobject, jlong deviceId, jboolean hasPendingTune) {
  std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
  if (it != sDvbManagers.end()) {
    it->second->setHasPendingTune(hasPendingTune);
  }
}

/*
 * Class:     com_android_tv_tuner_TunerHal
 * Method:    nativeGetDeliverySystemType
 * Signature: (J)I
 */
JNIEXPORT int JNICALL
Java_com_android_tv_tuner_TunerHal_nativeGetDeliverySystemType(JNIEnv *env,
                                                               jobject thiz,
                                                               jlong deviceId) {
  std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
  if (it != sDvbManagers.end()) {
    return it->second->getDeliverySystemType(env, thiz);
  } else {
    DvbManager *dvbManager = new DvbManager(env, thiz);
    sDvbManagers.insert(std::pair<jlong, DvbManager *>(deviceId, dvbManager));
    return dvbManager->getDeliverySystemType(env, thiz);
  }
}