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.

121 lines
3.7KB

  1. /*
  2. * SSA/ASS decoder
  3. * Copyright (c) 2010 Aurelien Jacobs <aurel@gnuage.org>
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include <string.h>
  22. #include "avcodec.h"
  23. #include "ass.h"
  24. #include "ass_split.h"
  25. #include "libavutil/internal.h"
  26. #include "libavutil/mem.h"
  27. static av_cold int ass_decode_init(AVCodecContext *avctx)
  28. {
  29. avctx->subtitle_header = av_malloc(avctx->extradata_size + 1);
  30. if (!avctx->subtitle_header)
  31. return AVERROR(ENOMEM);
  32. memcpy(avctx->subtitle_header, avctx->extradata, avctx->extradata_size);
  33. avctx->subtitle_header[avctx->extradata_size] = 0;
  34. avctx->subtitle_header_size = avctx->extradata_size;
  35. avctx->priv_data = ff_ass_split(avctx->extradata);
  36. if(!avctx->priv_data)
  37. return -1;
  38. return 0;
  39. }
  40. static int ass_decode_close(AVCodecContext *avctx)
  41. {
  42. ff_ass_split_free(avctx->priv_data);
  43. avctx->priv_data = NULL;
  44. return 0;
  45. }
  46. #if CONFIG_SSA_DECODER
  47. static int ssa_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr,
  48. AVPacket *avpkt)
  49. {
  50. const char *ptr = avpkt->data;
  51. int len, size = avpkt->size;
  52. while (size > 0) {
  53. int duration;
  54. ASSDialog *dialog = ff_ass_split_dialog(avctx->priv_data, ptr, 0, NULL);
  55. if (!dialog)
  56. return AVERROR_INVALIDDATA;
  57. duration = dialog->end - dialog->start;
  58. len = ff_ass_add_rect(data, ptr, 0, duration, 1);
  59. if (len < 0)
  60. return len;
  61. ptr += len;
  62. size -= len;
  63. }
  64. *got_sub_ptr = avpkt->size > 0;
  65. return avpkt->size;
  66. }
  67. AVCodec ff_ssa_decoder = {
  68. .name = "ssa",
  69. .long_name = NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) subtitle"),
  70. .type = AVMEDIA_TYPE_SUBTITLE,
  71. .id = AV_CODEC_ID_SSA,
  72. .init = ass_decode_init,
  73. .decode = ssa_decode_frame,
  74. .close = ass_decode_close,
  75. };
  76. #endif
  77. #if CONFIG_ASS_DECODER
  78. static int ass_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr,
  79. AVPacket *avpkt)
  80. {
  81. int ret;
  82. AVSubtitle *sub = data;
  83. const char *ptr = avpkt->data;
  84. static const AVRational ass_tb = {1, 100};
  85. const int ts_start = av_rescale_q(avpkt->pts, avctx->time_base, ass_tb);
  86. const int ts_duration = av_rescale_q(avpkt->duration, avctx->time_base, ass_tb);
  87. if (avpkt->size <= 0)
  88. return avpkt->size;
  89. ret = ff_ass_add_rect(sub, ptr, ts_start, ts_duration, 2);
  90. if (ret < 0) {
  91. if (ret == AVERROR_INVALIDDATA)
  92. av_log(avctx, AV_LOG_ERROR, "Invalid ASS packet\n");
  93. return ret;
  94. }
  95. *got_sub_ptr = avpkt->size > 0;
  96. return avpkt->size;
  97. }
  98. AVCodec ff_ass_decoder = {
  99. .name = "ass",
  100. .long_name = NULL_IF_CONFIG_SMALL("ASS (Advanced SubStation Alpha) subtitle"),
  101. .type = AVMEDIA_TYPE_SUBTITLE,
  102. .id = AV_CODEC_ID_ASS,
  103. .init = ass_decode_init,
  104. .decode = ass_decode_frame,
  105. .close = ass_decode_close,
  106. };
  107. #endif