You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

H264Decoder.cxx 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /* Copyright (C) 2021 Vladimir Sukhonosov <xornet@xornet.org>
  2. * Copyright (C) 2021 Martins Mozeiko <martins.mozeiko@gmail.com>
  3. * All Rights Reserved.
  4. *
  5. * This is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This software is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this software; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  18. * USA.
  19. */
  20. #define MAX_H264_INSTANCES 64
  21. #include <deque>
  22. #include <rdr/MemInStream.h>
  23. #include <rdr/InStream.h>
  24. #include <rdr/OutStream.h>
  25. #include <rfb/LogWriter.h>
  26. #include <rfb/Exception.h>
  27. #include <rfb/H264Decoder.h>
  28. #include <rfb/H264DecoderContext.h>
  29. using namespace rfb;
  30. static LogWriter vlog("H264Decoder");
  31. enum rectFlags {
  32. resetContext = 0x1,
  33. resetAllContexts = 0x2,
  34. };
  35. H264Decoder::H264Decoder() : Decoder(DecoderOrdered)
  36. {
  37. }
  38. H264Decoder::~H264Decoder()
  39. {
  40. resetContexts();
  41. }
  42. void H264Decoder::resetContexts()
  43. {
  44. os::AutoMutex lock(&mutex);
  45. for (std::deque<H264DecoderContext*>::iterator it = contexts.begin(); it != contexts.end(); it++)
  46. delete *it;
  47. contexts.clear();
  48. }
  49. H264DecoderContext* H264Decoder::findContext(const Rect& r)
  50. {
  51. os::AutoMutex m(&mutex);
  52. for (std::deque<H264DecoderContext*>::iterator it = contexts.begin(); it != contexts.end(); it++)
  53. if ((*it)->isEqualRect(r))
  54. return *it;
  55. return NULL;
  56. }
  57. bool H264Decoder::readRect(const Rect& /*r*/,
  58. rdr::InStream* is,
  59. const ServerParams& /*server*/,
  60. rdr::OutStream* os)
  61. {
  62. uint32_t len;
  63. if (!is->hasData(8))
  64. return false;
  65. is->setRestorePoint();
  66. len = is->readU32();
  67. os->writeU32(len);
  68. uint32_t flags = is->readU32();
  69. os->writeU32(flags);
  70. if (!is->hasDataOrRestore(len))
  71. return false;
  72. is->clearRestorePoint();
  73. os->copyBytes(is, len);
  74. return true;
  75. }
  76. void H264Decoder::decodeRect(const Rect& r, const uint8_t* buffer,
  77. size_t buflen,
  78. const ServerParams& /*server*/,
  79. ModifiablePixelBuffer* pb)
  80. {
  81. rdr::MemInStream is(buffer, buflen);
  82. uint32_t len = is.readU32();
  83. uint32_t flags = is.readU32();
  84. H264DecoderContext* ctx = NULL;
  85. if (flags & resetAllContexts)
  86. {
  87. resetContexts();
  88. if (!len)
  89. return;
  90. flags &= ~(resetContext | resetAllContexts);
  91. } else {
  92. ctx = findContext(r);
  93. }
  94. if (!ctx)
  95. {
  96. os::AutoMutex lock(&mutex);
  97. if (contexts.size() >= MAX_H264_INSTANCES)
  98. {
  99. H264DecoderContext* excess_ctx = contexts.front();
  100. delete excess_ctx;
  101. contexts.pop_front();
  102. }
  103. ctx = H264DecoderContext::createContext(r);
  104. if (!ctx)
  105. throw Exception("H264Decoder: Context not be created");
  106. contexts.push_back(ctx);
  107. }
  108. if (!ctx->isReady())
  109. throw Exception("H264Decoder: Context is not ready");
  110. if (flags & resetContext)
  111. ctx->reset();
  112. if (!len)
  113. return;
  114. ctx->decode(is.getptr(len), len, pb);
  115. }