VideoRendererAndroid.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. //
  2. // Created by Grishka on 12.08.2018.
  3. //
  4. #include "VideoRendererAndroid.h"
  5. #include "JNIUtilities.h"
  6. #include "../../PrivateDefines.h"
  7. #include "../../logging.h"
  8. using namespace tgvoip;
  9. using namespace tgvoip::video;
  10. jmethodID VideoRendererAndroid::resetMethod=NULL;
  11. jmethodID VideoRendererAndroid::decodeAndDisplayMethod=NULL;
  12. jmethodID VideoRendererAndroid::setStreamEnabledMethod=NULL;
  13. std::vector<uint32_t> VideoRendererAndroid::availableDecoders;
  14. int VideoRendererAndroid::maxResolution;
  15. extern JavaVM* sharedJVM;
  16. VideoRendererAndroid::VideoRendererAndroid(jobject jobj) : queue(50){
  17. this->jobj=jobj;
  18. }
  19. VideoRendererAndroid::~VideoRendererAndroid(){
  20. running=false;
  21. Request req{
  22. Buffer(0),
  23. Request::Type::Shutdown
  24. };
  25. queue.Put(std::move(req));
  26. thread->Join();
  27. delete thread;
  28. /*decoderThread.Post([this]{
  29. decoderEnv->DeleteGlobalRef(jobj);
  30. });*/
  31. }
  32. void VideoRendererAndroid::Reset(uint32_t codec, unsigned int width, unsigned int height, std::vector<Buffer> &_csd){
  33. csd.clear();
  34. for(Buffer& b:_csd){
  35. csd.push_back(Buffer::CopyOf(b));
  36. }
  37. this->codec=codec;
  38. this->width=width;
  39. this->height=height;
  40. Request req{
  41. Buffer(0),
  42. Request::Type::ResetDecoder
  43. };
  44. queue.Put(std::move(req));
  45. Request req2{
  46. Buffer(0),
  47. Request::Type::UpdateStreamState
  48. };
  49. queue.Put(std::move(req2));
  50. if(!thread){
  51. thread=new Thread(std::bind(&VideoRendererAndroid::RunThread, this));
  52. thread->Start();
  53. }
  54. }
  55. void VideoRendererAndroid::DecodeAndDisplay(Buffer frame, uint32_t pts){
  56. /*decoderThread.Post(std::bind([this](Buffer frame){
  57. }, std::move(frame)));*/
  58. //LOGV("2 before decode %u", (unsigned int)frame.Length());
  59. Request req{
  60. std::move(frame),
  61. Request::Type::DecodeFrame
  62. };
  63. queue.Put(std::move(req));
  64. }
  65. void VideoRendererAndroid::RunThread(){
  66. JNIEnv* env;
  67. sharedJVM->AttachCurrentThread(&env, NULL);
  68. constexpr size_t bufferSize=200*1024;
  69. unsigned char* buf=reinterpret_cast<unsigned char*>(malloc(bufferSize));
  70. jobject jbuf=env->NewDirectByteBuffer(buf, bufferSize);
  71. while(running){
  72. //LOGV("before get from queue");
  73. Request request=std::move(queue.GetBlocking());
  74. //LOGV("1 before decode %u", (unsigned int)request.Length());
  75. if(request.type==Request::Type::Shutdown){
  76. LOGI("Shutting down video decoder thread");
  77. break;
  78. }else if(request.type==Request::Type::DecodeFrame){
  79. if(request.buffer.Length()>bufferSize){
  80. LOGE("Frame data is too long (%u, max %u)", (int) request.buffer.Length(), (int) bufferSize);
  81. }else{
  82. memcpy(buf, *request.buffer, request.buffer.Length());
  83. env->CallVoidMethod(jobj, decodeAndDisplayMethod, jbuf, (jint) request.buffer.Length(), 0);
  84. }
  85. }else if(request.type==Request::Type::ResetDecoder){
  86. jobjectArray jcsd=NULL;
  87. if(!csd.empty()){
  88. jcsd=env->NewObjectArray((jsize)csd.size(), env->FindClass("[B"), NULL);
  89. jsize i=0;
  90. for(Buffer& b:csd){
  91. env->SetObjectArrayElement(jcsd, i, jni::BufferToByteArray(env, b));
  92. i++;
  93. }
  94. }
  95. std::string codecStr="";
  96. switch(codec){
  97. case CODEC_AVC:
  98. codecStr="video/avc";
  99. break;
  100. case CODEC_HEVC:
  101. codecStr="video/hevc";
  102. break;
  103. case CODEC_VP8:
  104. codecStr="video/x-vnd.on2.vp8";
  105. break;
  106. case CODEC_VP9:
  107. codecStr="video/x-vnd.on2.vp9";
  108. break;
  109. }
  110. env->CallVoidMethod(jobj, resetMethod, env->NewStringUTF(codecStr.c_str()), (jint)width, (jint)height, jcsd);
  111. }else if(request.type==Request::Type::UpdateStreamState){
  112. env->CallVoidMethod(jobj, setStreamEnabledMethod, streamEnabled);
  113. }
  114. }
  115. free(buf);
  116. sharedJVM->DetachCurrentThread();
  117. LOGI("==== decoder thread exiting ====");
  118. }
  119. void VideoRendererAndroid::SetStreamEnabled(bool enabled){
  120. LOGI("Video stream state: %d", enabled);
  121. /*decoderThread.Post([=](){
  122. decoderEnv->CallVoidMethod(jobj, setStreamEnabledMethod, enabled);
  123. });*/
  124. }