summaryrefslogtreecommitdiff
path: root/video_engine/test/android/jni/android_media_codec_decoder.cc
blob: ac12015c021241dd1617cac55f9fd967e481e6d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <android/log.h>
#define LOG_TAG "AndroidMediaCodecDecoder"

#include <jni.h>

#include "android_media_codec_decoder.h"

namespace webrtc {

AndroidMediaCodecDecoder::AndroidMediaCodecDecoder(
    JavaVM* vm, jobject surface, jclass decoderClass)
  : decode_complete_callback_(NULL),
    vm_(vm),
    surface_(surface),
    mediaCodecDecoder_(NULL),
    decoderClass_(decoderClass),
    env_(NULL),
    setEncodedImageID_(NULL),
    vm_attached_(false) {
}

int32_t AndroidMediaCodecDecoder::InitDecode(
    const VideoCodec* codecSettings, int32_t numberOfCores) {
  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "%s", __func__);

  // TODO(dwkang): Detach this thread from VM. => this leads to a crash on
  //               "StopCall".
  int ret = vm_->AttachCurrentThread(&env_, NULL);
  // Get the JNI env for this thread
  if ((ret < 0) || !env_) {
      __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
                          "Could not attach thread to JVM (%d, %p)", ret,
                          env_);
      return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
  } else {
    vm_attached_ = true;
  }

  // Initialize the media codec java decoder class.
  jmethodID mid = env_->GetMethodID(decoderClass_, "<init>", "()V");
  mediaCodecDecoder_ = env_->NewGlobalRef(env_->NewObject(decoderClass_, mid));

  mid = env_->GetMethodID(
      decoderClass_, "configure", "(Landroid/view/SurfaceView;II)V");
  env_->CallVoidMethod(mediaCodecDecoder_, mid, surface_,
                       codecSettings->width, codecSettings->height);

  setEncodedImageID_ = env_->GetMethodID(
      decoderClass_, "setEncodedImage", "(Ljava/nio/ByteBuffer;J)V");

  // Call start()
  jmethodID startID = env_->GetMethodID(decoderClass_, "start", "()V");
  env_->CallVoidMethod(mediaCodecDecoder_, startID);
  return WEBRTC_VIDEO_CODEC_OK;
}

int32_t AndroidMediaCodecDecoder::Decode(
    const EncodedImage& inputImage,
    bool missingFrames,
    const RTPFragmentationHeader* fragmentation,
    const CodecSpecificInfo* codecSpecificInfo,
    int64_t renderTimeMs) {
  if (!vm_attached_) {
    return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
  }

  jobject byteBuffer =
      env_->NewDirectByteBuffer(inputImage._buffer, inputImage._length);
  env_->CallVoidMethod(
      mediaCodecDecoder_, setEncodedImageID_, byteBuffer, renderTimeMs);
  env_->DeleteLocalRef(byteBuffer);

  return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
}

int32_t AndroidMediaCodecDecoder::RegisterDecodeCompleteCallback(
    DecodedImageCallback* callback) {
  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "%s", __func__);
  return WEBRTC_VIDEO_CODEC_OK;
}

int32_t AndroidMediaCodecDecoder::Release() {
  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "%s", __func__);
  env_->DeleteGlobalRef(mediaCodecDecoder_);
  mediaCodecDecoder_ = NULL;

  return WEBRTC_VIDEO_CODEC_OK;
}

int32_t AndroidMediaCodecDecoder::Reset() {
  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "%s", __func__);
  return WEBRTC_VIDEO_CODEC_OK;
}

}  // namespace webrtc