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.

166 lines
4.6KB

  1. /*
  2. * RTP VP8 Depacketizer
  3. * Copyright (c) 2010 Josh Allmann
  4. * Copyright (c) 2012 Martin Storsjo
  5. *
  6. * This file is part of Libav.
  7. *
  8. * Libav is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * Libav is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with Libav; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. /**
  23. * @file
  24. * @brief RTP support for the VP8 payload
  25. * @author Josh Allmann <joshua.allmann@gmail.com>
  26. * @see http://tools.ietf.org/html/draft-ietf-payload-vp8-05
  27. */
  28. #include "libavcodec/bytestream.h"
  29. #include "rtpdec_formats.h"
  30. struct PayloadContext {
  31. AVIOContext *data;
  32. uint32_t timestamp;
  33. };
  34. static void prepare_packet(AVPacket *pkt, PayloadContext *vp8, int stream)
  35. {
  36. av_init_packet(pkt);
  37. pkt->stream_index = stream;
  38. pkt->size = avio_close_dyn_buf(vp8->data, &pkt->data);
  39. pkt->destruct = av_destruct_packet;
  40. vp8->data = NULL;
  41. }
  42. static int vp8_handle_packet(AVFormatContext *ctx,
  43. PayloadContext *vp8,
  44. AVStream *st,
  45. AVPacket *pkt,
  46. uint32_t *timestamp,
  47. const uint8_t *buf,
  48. int len, int flags)
  49. {
  50. int start_partition, end_packet;
  51. int extended_bits, non_ref, part_id;
  52. int pictureid_present = 0, tl0picidx_present = 0, tid_present = 0,
  53. keyidx_present = 0;
  54. int pictureid = -1, keyidx = -1;
  55. if (len < 1)
  56. return AVERROR_INVALIDDATA;
  57. extended_bits = buf[0] & 0x80;
  58. non_ref = buf[0] & 0x20;
  59. start_partition = buf[0] & 0x10;
  60. part_id = buf[0] & 0x0f;
  61. end_packet = flags & RTP_FLAG_MARKER;
  62. buf++;
  63. len--;
  64. if (extended_bits) {
  65. if (len < 1)
  66. return AVERROR_INVALIDDATA;
  67. pictureid_present = buf[0] & 0x80;
  68. tl0picidx_present = buf[0] & 0x40;
  69. tid_present = buf[0] & 0x20;
  70. keyidx_present = buf[0] & 0x10;
  71. buf++;
  72. len--;
  73. }
  74. if (pictureid_present) {
  75. if (len < 1)
  76. return AVERROR_INVALIDDATA;
  77. if (buf[0] & 0x80) {
  78. if (len < 2)
  79. return AVERROR_INVALIDDATA;
  80. pictureid = AV_RB16(buf) & 0x7fff;
  81. buf += 2;
  82. len -= 2;
  83. } else {
  84. pictureid = buf[0] & 0x7f;
  85. buf++;
  86. len--;
  87. }
  88. }
  89. if (tl0picidx_present) {
  90. // Ignoring temporal level zero index
  91. buf++;
  92. len--;
  93. }
  94. if (tid_present || keyidx_present) {
  95. // Ignoring temporal layer index and layer sync bit
  96. if (len < 1)
  97. return AVERROR_INVALIDDATA;
  98. if (keyidx_present)
  99. keyidx = buf[0] & 0x1f;
  100. buf++;
  101. len--;
  102. }
  103. if (len < 1)
  104. return AVERROR_INVALIDDATA;
  105. if (start_partition && part_id == 0) {
  106. int res;
  107. if (vp8->data) {
  108. uint8_t *tmp;
  109. avio_close_dyn_buf(vp8->data, &tmp);
  110. av_free(tmp);
  111. vp8->data = NULL;
  112. }
  113. if ((res = avio_open_dyn_buf(&vp8->data)) < 0)
  114. return res;
  115. vp8->timestamp = *timestamp;
  116. }
  117. if (!vp8->data || vp8->timestamp != *timestamp) {
  118. av_log(ctx, AV_LOG_WARNING,
  119. "Received no start marker; dropping frame\n");
  120. return AVERROR(EAGAIN);
  121. }
  122. avio_write(vp8->data, buf, len);
  123. if (end_packet) {
  124. prepare_packet(pkt, vp8, st->index);
  125. return 0;
  126. }
  127. return AVERROR(EAGAIN);
  128. }
  129. static PayloadContext *vp8_new_context(void)
  130. {
  131. return av_mallocz(sizeof(PayloadContext));
  132. }
  133. static void vp8_free_context(PayloadContext *vp8)
  134. {
  135. if (vp8->data) {
  136. uint8_t *tmp;
  137. avio_close_dyn_buf(vp8->data, &tmp);
  138. av_free(tmp);
  139. }
  140. av_free(vp8);
  141. }
  142. RTPDynamicProtocolHandler ff_vp8_dynamic_handler = {
  143. .enc_name = "VP8",
  144. .codec_type = AVMEDIA_TYPE_VIDEO,
  145. .codec_id = AV_CODEC_ID_VP8,
  146. .alloc = vp8_new_context,
  147. .free = vp8_free_context,
  148. .parse_packet = vp8_handle_packet,
  149. };