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.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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, rdr::InStream* is,
  58. const ServerParams& server, rdr::OutStream* os)
  59. {
  60. rdr::U32 len;
  61. if (!is->hasData(8))
  62. return false;
  63. is->setRestorePoint();
  64. len = is->readU32();
  65. os->writeU32(len);
  66. rdr::U32 flags = is->readU32();
  67. os->writeU32(flags);
  68. if (!is->hasDataOrRestore(len))
  69. return false;
  70. is->clearRestorePoint();
  71. os->copyBytes(is, len);
  72. return true;
  73. }
  74. void H264Decoder::decodeRect(const Rect& r, const void* buffer,
  75. size_t buflen, const ServerParams& server,
  76. ModifiablePixelBuffer* pb)
  77. {
  78. rdr::MemInStream is(buffer, buflen);
  79. rdr::U32 len = is.readU32();
  80. rdr::U32 flags = is.readU32();
  81. H264DecoderContext* ctx = NULL;
  82. if (flags & resetAllContexts)
  83. {
  84. resetContexts();
  85. if (!len)
  86. return;
  87. flags &= ~(resetContext | resetAllContexts);
  88. } else {
  89. ctx = findContext(r);
  90. }
  91. if (!ctx)
  92. {
  93. os::AutoMutex lock(&mutex);
  94. if (contexts.size() >= MAX_H264_INSTANCES)
  95. {
  96. auto excecc_ctx = contexts.front();
  97. delete excecc_ctx;
  98. contexts.pop_front();
  99. }
  100. ctx = H264DecoderContext::createContext(r);
  101. if (!ctx)
  102. throw Exception("H264Decoder: Context not be created");
  103. contexts.push_back(ctx);
  104. }
  105. if (!ctx->isReady())
  106. throw Exception("H264Decoder: Context is not ready");
  107. if (flags & resetContext)
  108. ctx->reset();
  109. if (!len)
  110. return;
  111. ctx->decode(is.getptr(len), len, flags, pb);
  112. }