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.

147 lines
4.4KB

  1. /*
  2. * This file is part of Libav.
  3. *
  4. * Libav is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * Libav is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with Libav; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. /**
  19. * @file
  20. * This bitstream filter splits VP9 superframes into packets containing
  21. * just one frame.
  22. */
  23. #include <stddef.h>
  24. #include "avcodec.h"
  25. #include "bsf.h"
  26. #include "bitstream.h"
  27. #include "bytestream.h"
  28. typedef struct VP9SFSplitContext {
  29. AVPacket *buffer_pkt;
  30. int nb_frames;
  31. int next_frame;
  32. size_t next_frame_offset;
  33. int sizes[8];
  34. } VP9SFSplitContext;
  35. static int vp9_superframe_split_filter(AVBSFContext *ctx, AVPacket *out)
  36. {
  37. VP9SFSplitContext *s = ctx->priv_data;
  38. AVPacket *in;
  39. int i, j, ret, marker;
  40. int is_superframe = !!s->buffer_pkt;
  41. if (!s->buffer_pkt) {
  42. ret = ff_bsf_get_packet(ctx, &s->buffer_pkt);
  43. if (ret < 0)
  44. return ret;
  45. in = s->buffer_pkt;
  46. marker = in->data[in->size - 1];
  47. if ((marker & 0xe0) == 0xc0) {
  48. int length_size = 1 + ((marker >> 3) & 0x3);
  49. int nb_frames = 1 + (marker & 0x7);
  50. int idx_size = 2 + nb_frames * length_size;
  51. if (in->size >= idx_size && in->data[in->size - idx_size] == marker) {
  52. GetByteContext bc;
  53. int total_size = 0;
  54. bytestream2_init(&bc, in->data + in->size + 1 - idx_size,
  55. nb_frames * length_size);
  56. for (i = 0; i < nb_frames; i++) {
  57. int frame_size = 0;
  58. for (j = 0; j < length_size; j++)
  59. frame_size |= bytestream2_get_byte(&bc) << (j * 8);
  60. total_size += frame_size;
  61. if (total_size > in->size - idx_size) {
  62. av_log(ctx, AV_LOG_ERROR,
  63. "Invalid frame size in a superframe: %d\n", frame_size);
  64. ret = AVERROR(EINVAL);
  65. goto fail;
  66. }
  67. s->sizes[i] = frame_size;
  68. }
  69. s->nb_frames = nb_frames;
  70. s->next_frame = 0;
  71. s->next_frame_offset = 0;
  72. is_superframe = 1;
  73. }
  74. }
  75. }
  76. if (is_superframe) {
  77. BitstreamContext bc;
  78. int profile, invisible = 0;
  79. ret = av_packet_ref(out, s->buffer_pkt);
  80. if (ret < 0)
  81. goto fail;
  82. out->data += s->next_frame_offset;
  83. out->size = s->sizes[s->next_frame];
  84. s->next_frame_offset += out->size;
  85. s->next_frame++;
  86. if (s->next_frame >= s->nb_frames)
  87. av_packet_free(&s->buffer_pkt);
  88. ret = bitstream_init8(&bc, out->data, out->size);
  89. if (ret < 0)
  90. goto fail;
  91. bitstream_read(&bc, 2); // frame_marker
  92. profile = bitstream_read(&bc, 1);
  93. profile |= bitstream_read(&bc, 1) << 1;
  94. if (profile == 3)
  95. bitstream_read(&bc, 1);
  96. if (!bitstream_read(&bc, 1)) {
  97. bitstream_read(&bc, 1);
  98. invisible = !bitstream_read(&bc, 1);
  99. }
  100. if (invisible)
  101. out->pts = AV_NOPTS_VALUE;
  102. } else {
  103. av_packet_move_ref(out, s->buffer_pkt);
  104. av_packet_free(&s->buffer_pkt);
  105. }
  106. return 0;
  107. fail:
  108. av_packet_free(&s->buffer_pkt);
  109. return ret;
  110. }
  111. static void vp9_superframe_split_uninit(AVBSFContext *ctx)
  112. {
  113. VP9SFSplitContext *s = ctx->priv_data;
  114. av_packet_free(&s->buffer_pkt);
  115. }
  116. const AVBitStreamFilter ff_vp9_superframe_split_bsf = {
  117. .name = "vp9_superframe_split",
  118. .priv_data_size = sizeof(VP9SFSplitContext),
  119. .close = vp9_superframe_split_uninit,
  120. .filter = vp9_superframe_split_filter,
  121. .codec_ids = (const enum AVCodecID []){ AV_CODEC_ID_VP9, AV_CODEC_ID_NONE },
  122. };