Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * RTP packetization for H.264 (RFC3984)
  3.  * RTP packetizer for HEVC/H.265 payload format (draft version 6)
  4.  * Copyright (c) 2008 Luca Abeni
  5.  * Copyright (c) 2014 Thomas Volkert <thomas@homer-conferencing.com>
  6.  *
  7.  * This file is part of FFmpeg.
  8.  *
  9.  * FFmpeg is free software; you can redistribute it and/or
  10.  * modify it under the terms of the GNU Lesser General Public
  11.  * License as published by the Free Software Foundation; either
  12.  * version 2.1 of the License, or (at your option) any later version.
  13.  *
  14.  * FFmpeg is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17.  * Lesser General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU Lesser General Public
  20.  * License along with FFmpeg; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22.  */
  23.  
  24. /**
  25.  * @file
  26.  * @brief H.264/HEVC packetization
  27.  * @author Luca Abeni <lucabe72@email.it>
  28.  */
  29.  
  30. #include "libavutil/intreadwrite.h"
  31.  
  32. #include "avformat.h"
  33. #include "avc.h"
  34. #include "rtpenc.h"
  35.  
  36. static void flush_buffered(AVFormatContext *s1, int last)
  37. {
  38.     RTPMuxContext *s = s1->priv_data;
  39.     if (s->buf_ptr != s->buf) {
  40.         // If we're only sending one single NAL unit, send it as such, skip
  41.         // the STAP-A/AP framing
  42.         if (s->buffered_nals == 1) {
  43.             enum AVCodecID codec = s1->streams[0]->codec->codec_id;
  44.             if (codec == AV_CODEC_ID_H264)
  45.                 ff_rtp_send_data(s1, s->buf + 3, s->buf_ptr - s->buf - 3, last);
  46.             else
  47.                 ff_rtp_send_data(s1, s->buf + 4, s->buf_ptr - s->buf - 4, last);
  48.         } else
  49.             ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, last);
  50.     }
  51.     s->buf_ptr = s->buf;
  52.     s->buffered_nals = 0;
  53. }
  54.  
  55. static void nal_send(AVFormatContext *s1, const uint8_t *buf, int size, int last)
  56. {
  57.     RTPMuxContext *s = s1->priv_data;
  58.     enum AVCodecID codec = s1->streams[0]->codec->codec_id;
  59.  
  60.     av_log(s1, AV_LOG_DEBUG, "Sending NAL %x of len %d M=%d\n", buf[0] & 0x1F, size, last);
  61.     if (size <= s->max_payload_size) {
  62.         int buffered_size = s->buf_ptr - s->buf;
  63.         int header_size;
  64.         int skip_aggregate = 0;
  65.  
  66.         if (codec == AV_CODEC_ID_H264) {
  67.             header_size = 1;
  68.             skip_aggregate = s->flags & FF_RTP_FLAG_H264_MODE0;
  69.         } else {
  70.             header_size = 2;
  71.         }
  72.  
  73.         // Flush buffered NAL units if the current unit doesn't fit
  74.         if (buffered_size + 2 + size > s->max_payload_size) {
  75.             flush_buffered(s1, 0);
  76.             buffered_size = 0;
  77.         }
  78.         // If we aren't using mode 0, and the NAL unit fits including the
  79.         // framing (2 bytes length, plus 1/2 bytes for the STAP-A/AP marker),
  80.         // write the unit to the buffer as a STAP-A/AP packet, otherwise flush
  81.         // and send as single NAL.
  82.         if (buffered_size + 2 + header_size + size <= s->max_payload_size &&
  83.             !skip_aggregate) {
  84.             if (buffered_size == 0) {
  85.                 if (codec == AV_CODEC_ID_H264) {
  86.                     *s->buf_ptr++ = 24;
  87.                 } else {
  88.                     *s->buf_ptr++ = 48 << 1;
  89.                     *s->buf_ptr++ = 1;
  90.                 }
  91.             }
  92.             AV_WB16(s->buf_ptr, size);
  93.             s->buf_ptr += 2;
  94.             memcpy(s->buf_ptr, buf, size);
  95.             s->buf_ptr += size;
  96.             s->buffered_nals++;
  97.         } else {
  98.             flush_buffered(s1, 0);
  99.             ff_rtp_send_data(s1, buf, size, last);
  100.         }
  101.     } else {
  102.         int flag_byte, header_size;
  103.         flush_buffered(s1, 0);
  104.         if (codec == AV_CODEC_ID_H264 && (s->flags & FF_RTP_FLAG_H264_MODE0)) {
  105.             av_log(s1, AV_LOG_ERROR,
  106.                    "NAL size %d > %d, try -slice-max-size %d\n", size,
  107.                    s->max_payload_size, s->max_payload_size);
  108.             return;
  109.         }
  110.         av_log(s1, AV_LOG_DEBUG, "NAL size %d > %d\n", size, s->max_payload_size);
  111.         if (codec == AV_CODEC_ID_H264) {
  112.             uint8_t type = buf[0] & 0x1F;
  113.             uint8_t nri = buf[0] & 0x60;
  114.  
  115.             s->buf[0] = 28;        /* FU Indicator; Type = 28 ---> FU-A */
  116.             s->buf[0] |= nri;
  117.             s->buf[1] = type;
  118.             s->buf[1] |= 1 << 7;
  119.             buf  += 1;
  120.             size -= 1;
  121.  
  122.             flag_byte   = 1;
  123.             header_size = 2;
  124.         } else {
  125.             uint8_t nal_type = (buf[0] >> 1) & 0x3F;
  126.             /*
  127.              * create the HEVC payload header and transmit the buffer as fragmentation units (FU)
  128.              *
  129.              *    0                   1
  130.              *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  131.              *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  132.              *   |F|   Type    |  LayerId  | TID |
  133.              *   +-------------+-----------------+
  134.              *
  135.              *      F       = 0
  136.              *      Type    = 49 (fragmentation unit (FU))
  137.              *      LayerId = 0
  138.              *      TID     = 1
  139.              */
  140.             s->buf[0] = 49 << 1;
  141.             s->buf[1] = 1;
  142.  
  143.             /*
  144.              *     create the FU header
  145.              *
  146.              *     0 1 2 3 4 5 6 7
  147.              *    +-+-+-+-+-+-+-+-+
  148.              *    |S|E|  FuType   |
  149.              *    +---------------+
  150.              *
  151.              *       S       = variable
  152.              *       E       = variable
  153.              *       FuType  = NAL unit type
  154.              */
  155.             s->buf[2]  = nal_type;
  156.             /* set the S bit: mark as start fragment */
  157.             s->buf[2] |= 1 << 7;
  158.  
  159.             /* pass the original NAL header */
  160.             buf  += 2;
  161.             size -= 2;
  162.  
  163.             flag_byte   = 2;
  164.             header_size = 3;
  165.         }
  166.  
  167.         while (size + header_size > s->max_payload_size) {
  168.             memcpy(&s->buf[header_size], buf, s->max_payload_size - header_size);
  169.             ff_rtp_send_data(s1, s->buf, s->max_payload_size, 0);
  170.             buf  += s->max_payload_size - header_size;
  171.             size -= s->max_payload_size - header_size;
  172.             s->buf[flag_byte] &= ~(1 << 7);
  173.         }
  174.         s->buf[flag_byte] |= 1 << 6;
  175.         memcpy(&s->buf[header_size], buf, size);
  176.         ff_rtp_send_data(s1, s->buf, size + header_size, last);
  177.     }
  178. }
  179.  
  180. void ff_rtp_send_h264_hevc(AVFormatContext *s1, const uint8_t *buf1, int size)
  181. {
  182.     const uint8_t *r, *end = buf1 + size;
  183.     RTPMuxContext *s = s1->priv_data;
  184.  
  185.     s->timestamp = s->cur_timestamp;
  186.     s->buf_ptr   = s->buf;
  187.     if (s->nal_length_size)
  188.         r = ff_avc_mp4_find_startcode(buf1, end, s->nal_length_size) ? buf1 : end;
  189.     else
  190.         r = ff_avc_find_startcode(buf1, end);
  191.     while (r < end) {
  192.         const uint8_t *r1;
  193.  
  194.         if (s->nal_length_size) {
  195.             r1 = ff_avc_mp4_find_startcode(r, end, s->nal_length_size);
  196.             if (!r1)
  197.                 r1 = end;
  198.             r += s->nal_length_size;
  199.         } else {
  200.             while (!*(r++));
  201.             r1 = ff_avc_find_startcode(r, end);
  202.         }
  203.         nal_send(s1, r, r1 - r, r1 == end);
  204.         r = r1;
  205.     }
  206.     flush_buffered(s1, 1);
  207. }
  208.