subtitle_stream.cpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #include "subtitle_stream.h"
  2. #include <c10/util/Logging.h>
  3. #include <limits>
  4. #include "util.h"
  5. namespace ffmpeg {
  6. const AVRational timeBaseQ = AVRational{1, AV_TIME_BASE};
  7. SubtitleStream::SubtitleStream(
  8. AVFormatContext* inputCtx,
  9. int index,
  10. bool convertPtsToWallTime,
  11. const SubtitleFormat& format)
  12. : Stream(
  13. inputCtx,
  14. MediaFormat::makeMediaFormat(format, index),
  15. convertPtsToWallTime,
  16. 0) {
  17. memset(&sub_, 0, sizeof(sub_));
  18. }
  19. void SubtitleStream::releaseSubtitle() {
  20. if (sub_.release) {
  21. avsubtitle_free(&sub_);
  22. memset(&sub_, 0, sizeof(sub_));
  23. }
  24. }
  25. SubtitleStream::~SubtitleStream() {
  26. releaseSubtitle();
  27. sampler_.shutdown();
  28. }
  29. int SubtitleStream::initFormat() {
  30. if (!codecCtx_->subtitle_header) {
  31. LOG(ERROR) << "No subtitle header found";
  32. } else {
  33. VLOG(1) << "Subtitle header found!";
  34. }
  35. return 0;
  36. }
  37. int SubtitleStream::analyzePacket(const AVPacket* packet, bool* gotFrame) {
  38. // clean-up
  39. releaseSubtitle();
  40. // FIXME: should this even be created?
  41. AVPacket* avPacket;
  42. avPacket = av_packet_alloc();
  43. if (avPacket == nullptr) {
  44. LOG(ERROR)
  45. << "decoder as not able to allocate the subtitle-specific packet.";
  46. // alternative to ENOMEM
  47. return AVERROR_BUFFER_TOO_SMALL;
  48. }
  49. avPacket->data = nullptr;
  50. avPacket->size = 0;
  51. // check flush packet
  52. auto pkt = packet ? packet : avPacket;
  53. int gotFramePtr = 0;
  54. // is these a better way than cast from const?
  55. int result =
  56. avcodec_decode_subtitle2(codecCtx_, &sub_, &gotFramePtr, (AVPacket*)pkt);
  57. if (result < 0) {
  58. LOG(ERROR) << "avcodec_decode_subtitle2 failed, err: "
  59. << Util::generateErrorDesc(result);
  60. // free the packet we've created
  61. av_packet_free(&avPacket);
  62. return result;
  63. } else if (result == 0) {
  64. result = pkt->size; // discard the rest of the package
  65. }
  66. sub_.release = gotFramePtr;
  67. *gotFrame = gotFramePtr > 0;
  68. // set proper pts in us
  69. if (gotFramePtr) {
  70. sub_.pts = av_rescale_q(
  71. pkt->pts, inputCtx_->streams[format_.stream]->time_base, timeBaseQ);
  72. }
  73. av_packet_free(&avPacket);
  74. return result;
  75. }
  76. int SubtitleStream::copyFrameBytes(ByteStorage* out, bool flush) {
  77. return sampler_.sample(flush ? nullptr : &sub_, out);
  78. }
  79. void SubtitleStream::setFramePts(DecoderHeader* header, bool) {
  80. header->pts = sub_.pts; // already in us
  81. }
  82. } // namespace ffmpeg