Advertisement
ngaullier

Untitled

Feb 20th, 2024
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 5.16 KB | None | 0 0
  1. From 37f1a07904d164ada5dd0af82cca3742e916bd82 Mon Sep 17 00:00:00 2001
  2. From: Nicolas Gaullier <nicolas.gaullier@cji.paris>
  3. Date: Fri, 2 Feb 2024 12:34:39 +0100
  4. Subject: [PATCH] avformat/mpegts: fix first NAL start code splited in two
  5.  different packets
  6.  
  7. When PES are not aligned and a tiny nal-encoded frame is contained in a single TS packet,
  8. the first NAL startcode may be split by the PES boundary, making the packet unworkable.
  9. This patch shift the PES boundaries to avoid this.
  10. ---
  11. libavformat/mpegts.c | 45 ++++++++++++++++++++++++++++++++++++++++++--
  12.  1 file changed, 43 insertions(+), 2 deletions(-)
  13.  
  14. diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
  15. index 836d5dd5a3..8f3bdfc690 100644
  16. --- a/libavformat/mpegts.c
  17. +++ b/libavformat/mpegts.c
  18. @@ -1148,6 +1148,7 @@ static int mpegts_push_data(MpegTSFilter *filter,
  19.      PESContext *pes   = filter->u.pes_filter.opaque;
  20.      MpegTSContext *ts = pes->ts;
  21.      const uint8_t *p;
  22. +    int pes_align_shift = 0;
  23.      int ret, len;
  24.  
  25.      if (!ts->pkt)
  26. @@ -1155,6 +1156,39 @@ static int mpegts_push_data(MpegTSFilter *filter,
  27.  
  28.      if (is_start) {
  29.          if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) {
  30. +            if ((pes->st->codecpar->codec_id == AV_CODEC_ID_H264
  31. +             || pes->st->codecpar->codec_id == AV_CODEC_ID_HEVC)
  32. +                && pes->data_index < TS_PACKET_SIZE - 4 - PES_HEADER_SIZE
  33. +                && pes->data_index >= 4
  34. +                && buf_size >= 4 ) {
  35. +                    /* check/avoid spliting the start code + first byte of the first NAL unit in two different packets.
  36. +                     * this could happen with a tiny unaligned PES that fits in a single ts packet. */
  37. +                    uint8_t *last_p_end = pes->buffer->data + pes->data_index - 4;
  38. +                    p = buf + PES_HEADER_SIZE + buf[PES_HEADER_SIZE - 1];
  39. +                    if (last_p_end[3] == 0x00 && AV_RB24(p) == 0x000001)
  40. +                        pes_align_shift = 4;
  41. +                    else if (AV_RB16(last_p_end + 2)== 0x0000 && AV_RB16(p) == 0x0001)
  42. +                        pes_align_shift = 3;
  43. +                    else if (AV_RB24(last_p_end + 1)== 0x000000 && *p == 0x01)
  44. +                        pes_align_shift = 2;
  45. +                    else if (AV_RB32(last_p_end) == 0x00000001)
  46. +                        pes_align_shift = 1;
  47. +                    if (pes_align_shift)
  48. +                    {
  49. +                        if (pes->PES_packet_length)
  50. +                            pes->PES_packet_length += pes_align_shift;
  51. +                        last_p_end += 4;
  52. +                        if (pes_align_shift > 3)
  53. +                            *last_p_end++ = 0x00;
  54. +                        if (pes_align_shift > 2)
  55. +                            *last_p_end++ = 0x00;
  56. +                        if (pes_align_shift > 1)
  57. +                            *last_p_end++ = 0x01;
  58. +                        *last_p_end = *(p + pes_align_shift - 1);
  59. +                        pes->data_index += pes_align_shift;
  60. +                        buf_size -= pes_align_shift;
  61. +                    }
  62. +                }
  63.              ret = new_pes_packet(pes, ts->pkt);
  64.              if (ret < 0)
  65.                  return ret;
  66. @@ -1206,6 +1240,8 @@ static int mpegts_push_data(MpegTSFilter *filter,
  67.                      }
  68.  
  69.                      pes->PES_packet_length = AV_RB16(pes->header + 4);
  70. +                    if (pes->PES_packet_length)
  71. +                        pes->PES_packet_length -= pes_align_shift;
  72.                      /* NOTE: zero length means the PES size is unbounded */
  73.  
  74.                      if (pes->stream_id != STREAM_ID_PROGRAM_STREAM_MAP &&
  75. @@ -1300,6 +1336,7 @@ skip:
  76.                  /* we got the full header. We parse it and get the payload */
  77.                  pes->state = MPEGTS_PAYLOAD;
  78.                  pes->data_index = 0;
  79. +                p += pes_align_shift;
  80.                  if (pes->stream_type == 0x12 && buf_size > 0) {
  81.                      int sl_header_bytes = read_sl_header(pes, &pes->sl, p,
  82.                                                           buf_size);
  83. @@ -1408,9 +1445,13 @@ skip:
  84.                  pes->data_index += buf_size;
  85.                  /* emit complete packets with known packet size
  86.                   * decreases demuxer delay for infrequent packets like subtitles from
  87. -                 * a couple of seconds to milliseconds for properly muxed files. */
  88. +                 * a couple of seconds to milliseconds for properly muxed files.
  89. +                 * disabled for video/NALs because at this point it could split/break the first NAL start code.
  90. +                 */
  91.                  if (!ts->stop_parse && pes->PES_packet_length &&
  92. -                    pes->pes_header_size + pes->data_index == pes->PES_packet_length + PES_START_SIZE) {
  93. +                    pes->pes_header_size + pes->data_index == pes->PES_packet_length + PES_START_SIZE &&
  94. +                    pes->st->codecpar->codec_id != AV_CODEC_ID_H264 &&
  95. +                    pes->st->codecpar->codec_id != AV_CODEC_ID_HEVC) {
  96.                      ts->stop_parse = 1;
  97.                      ret = new_pes_packet(pes, ts->pkt);
  98.                      pes->state = MPEGTS_SKIP;
  99. --
  100. 2.30.2
  101.  
  102.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement