Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * H.264 MP4 to Annex B byte stream format filter
  3.  * Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
  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.  
  22. #include <string.h>
  23.  
  24. #include "libavutil/intreadwrite.h"
  25. #include "libavutil/mem.h"
  26. #include "avcodec.h"
  27.  
  28. typedef struct H264BSFContext {
  29.     int32_t  sps_offset;
  30.     int32_t  pps_offset;
  31.     uint8_t  length_size;
  32.     uint8_t  new_idr;
  33.     uint8_t  idr_sps_seen;
  34.     uint8_t  idr_pps_seen;
  35.     int      extradata_parsed;
  36.  
  37.     /* When private_spspps is zero then spspps_buf points to global extradata
  38.        and bsf does replace a global extradata to own-allocated version (default
  39.        behaviour).
  40.        When private_spspps is non-zero the bsf uses a private version of spspps buf.
  41.        This mode necessary when bsf uses in decoder, else bsf has issues after
  42.        decoder re-initialization. Use the "private_spspps_buf" argument to
  43.        activate this mode.
  44.      */
  45.     int      private_spspps;
  46.     uint8_t *spspps_buf;
  47.     uint32_t spspps_size;
  48. } H264BSFContext;
  49.  
  50. static int alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size,
  51.                           const uint8_t *sps_pps, uint32_t sps_pps_size,
  52.                           const uint8_t *in, uint32_t in_size)
  53. {
  54.     uint32_t offset         = *poutbuf_size;
  55.     uint8_t nal_header_size = offset ? 3 : 4;
  56.     int err;
  57.  
  58.     *poutbuf_size += sps_pps_size + in_size + nal_header_size;
  59.     if ((err = av_reallocp(poutbuf,
  60.                            *poutbuf_size + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
  61.         *poutbuf_size = 0;
  62.         return err;
  63.     }
  64.     if (sps_pps)
  65.         memcpy(*poutbuf + offset, sps_pps, sps_pps_size);
  66.     memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size);
  67.     if (!offset) {
  68.         AV_WB32(*poutbuf + sps_pps_size, 1);
  69.     } else {
  70.         (*poutbuf + offset + sps_pps_size)[0] =
  71.         (*poutbuf + offset + sps_pps_size)[1] = 0;
  72.         (*poutbuf + offset + sps_pps_size)[2] = 1;
  73.     }
  74.  
  75.     return 0;
  76. }
  77.  
  78. static int h264_extradata_to_annexb(H264BSFContext *ctx, AVCodecContext *avctx, const int padding)
  79. {
  80.     uint16_t unit_size;
  81.     uint64_t total_size                 = 0;
  82.     uint8_t *out                        = NULL, unit_nb, sps_done = 0,
  83.              sps_seen                   = 0, pps_seen = 0;
  84.     const uint8_t *extradata            = avctx->extradata + 4;
  85.     static const uint8_t nalu_header[4] = { 0, 0, 0, 1 };
  86.     int length_size = (*extradata++ & 0x3) + 1; // retrieve length coded size
  87.  
  88.     ctx->sps_offset = ctx->pps_offset = -1;
  89.  
  90.     /* retrieve sps and pps unit(s) */
  91.     unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */
  92.     if (!unit_nb) {
  93.         goto pps;
  94.     } else {
  95.         ctx->sps_offset = 0;
  96.         sps_seen = 1;
  97.     }
  98.  
  99.     while (unit_nb--) {
  100.         int err;
  101.  
  102.         unit_size   = AV_RB16(extradata);
  103.         total_size += unit_size + 4;
  104.         if (total_size > INT_MAX - padding) {
  105.             av_log(avctx, AV_LOG_ERROR,
  106.                    "Too big extradata size, corrupted stream or invalid MP4/AVCC bitstream\n");
  107.             av_free(out);
  108.             return AVERROR(EINVAL);
  109.         }
  110.         if (extradata + 2 + unit_size > avctx->extradata + avctx->extradata_size) {
  111.             av_log(avctx, AV_LOG_ERROR, "Packet header is not contained in global extradata, "
  112.                    "corrupted stream or invalid MP4/AVCC bitstream\n");
  113.             av_free(out);
  114.             return AVERROR(EINVAL);
  115.         }
  116.         if ((err = av_reallocp(&out, total_size + padding)) < 0)
  117.             return err;
  118.         memcpy(out + total_size - unit_size - 4, nalu_header, 4);
  119.         memcpy(out + total_size - unit_size, extradata + 2, unit_size);
  120.         extradata += 2 + unit_size;
  121. pps:
  122.         if (!unit_nb && !sps_done++) {
  123.             unit_nb = *extradata++; /* number of pps unit(s) */
  124.             if (unit_nb) {
  125.                 ctx->pps_offset = total_size;
  126.                 pps_seen = 1;
  127.             }
  128.         }
  129.     }
  130.  
  131.     if (out)
  132.         memset(out + total_size, 0, padding);
  133.  
  134.     if (!sps_seen)
  135.         av_log(avctx, AV_LOG_WARNING,
  136.                "Warning: SPS NALU missing or invalid. "
  137.                "The resulting stream may not play.\n");
  138.  
  139.     if (!pps_seen)
  140.         av_log(avctx, AV_LOG_WARNING,
  141.                "Warning: PPS NALU missing or invalid. "
  142.                "The resulting stream may not play.\n");
  143.  
  144.     if (!ctx->private_spspps) {
  145.         av_free(avctx->extradata);
  146.         avctx->extradata      = out;
  147.         avctx->extradata_size = total_size;
  148.     }
  149.     ctx->spspps_buf  = out;
  150.     ctx->spspps_size = total_size;
  151.  
  152.     return length_size;
  153. }
  154.  
  155. static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
  156.                                    AVCodecContext *avctx, const char *args,
  157.                                    uint8_t **poutbuf, int *poutbuf_size,
  158.                                    const uint8_t *buf, int buf_size,
  159.                                    int keyframe)
  160. {
  161.     H264BSFContext *ctx = bsfc->priv_data;
  162.     int i;
  163.     uint8_t unit_type;
  164.     int32_t nal_size;
  165.     uint32_t cumul_size    = 0;
  166.     const uint8_t *buf_end = buf + buf_size;
  167.     int ret = 0;
  168.  
  169.     /* nothing to filter */
  170.     if (!avctx->extradata || avctx->extradata_size < 6) {
  171.         *poutbuf      = (uint8_t *)buf;
  172.         *poutbuf_size = buf_size;
  173.         return 0;
  174.     }
  175.  
  176.     /* retrieve sps and pps NAL units from extradata */
  177.     if (!ctx->extradata_parsed) {
  178.         if (args && strstr(args, "private_spspps_buf"))
  179.             ctx->private_spspps = 1;
  180.  
  181.         ret = h264_extradata_to_annexb(ctx, avctx, AV_INPUT_BUFFER_PADDING_SIZE);
  182.         if (ret < 0)
  183.             return ret;
  184.         ctx->length_size      = ret;
  185.         ctx->new_idr          = 1;
  186.         ctx->idr_sps_seen     = 0;
  187.         ctx->idr_pps_seen     = 0;
  188.         ctx->extradata_parsed = 1;
  189.     }
  190.  
  191.     *poutbuf_size = 0;
  192.     *poutbuf      = NULL;
  193.     do {
  194.         ret= AVERROR(EINVAL);
  195.         if (buf + ctx->length_size > buf_end)
  196.             goto fail;
  197.  
  198.         for (nal_size = 0, i = 0; i<ctx->length_size; i++)
  199.             nal_size = (nal_size << 8) | buf[i];
  200.  
  201.         buf      += ctx->length_size;
  202.         unit_type = *buf & 0x1f;
  203.  
  204.         if (nal_size > buf_end - buf || nal_size < 0)
  205.             goto fail;
  206.  
  207.         if (unit_type == 7)
  208.             ctx->idr_sps_seen = ctx->new_idr = 1;
  209.         else if (unit_type == 8) {
  210.             ctx->idr_pps_seen = ctx->new_idr = 1;
  211.             /* if SPS has not been seen yet, prepend the AVCC one to PPS */
  212.             if (!ctx->idr_sps_seen) {
  213.                 if (ctx->sps_offset == -1)
  214.                     av_log(avctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n");
  215.                 else {
  216.                     if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
  217.                                          ctx->spspps_buf + ctx->sps_offset,
  218.                                          ctx->pps_offset != -1 ? ctx->pps_offset : ctx->spspps_size - ctx->sps_offset,
  219.                                          buf, nal_size)) < 0)
  220.                         goto fail;
  221.                     ctx->idr_sps_seen = 1;
  222.                     goto next_nal;
  223.                 }
  224.             }
  225.         }
  226.  
  227.         /* if this is a new IDR picture following an IDR picture, reset the idr flag.
  228.          * Just check first_mb_in_slice to be 0 as this is the simplest solution.
  229.          * This could be checking idr_pic_id instead, but would complexify the parsing. */
  230.         if (!ctx->new_idr && unit_type == 5 && (buf[1] & 0x80))
  231.             ctx->new_idr = 1;
  232.  
  233.         /* prepend only to the first type 5 NAL unit of an IDR picture, if no sps/pps are already present */
  234.         if (ctx->new_idr && unit_type == 5 && !ctx->idr_sps_seen && !ctx->idr_pps_seen) {
  235.             if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
  236.                                ctx->spspps_buf, ctx->spspps_size,
  237.                                buf, nal_size)) < 0)
  238.                 goto fail;
  239.             ctx->new_idr = 0;
  240.         /* if only SPS has been seen, also insert PPS */
  241.         } else if (ctx->new_idr && unit_type == 5 && ctx->idr_sps_seen && !ctx->idr_pps_seen) {
  242.             if (ctx->pps_offset == -1) {
  243.                 av_log(avctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n");
  244.                 if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
  245.                                      NULL, 0, buf, nal_size)) < 0)
  246.                     goto fail;
  247.             } else if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
  248.                                         ctx->spspps_buf + ctx->pps_offset, ctx->spspps_size - ctx->pps_offset,
  249.                                         buf, nal_size)) < 0)
  250.                 goto fail;
  251.         } else {
  252.             if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
  253.                                NULL, 0, buf, nal_size)) < 0)
  254.                 goto fail;
  255.             if (!ctx->new_idr && unit_type == 1) {
  256.                 ctx->new_idr = 1;
  257.                 ctx->idr_sps_seen = 0;
  258.                 ctx->idr_pps_seen = 0;
  259.             }
  260.         }
  261.  
  262. next_nal:
  263.         buf        += nal_size;
  264.         cumul_size += nal_size + ctx->length_size;
  265.     } while (cumul_size < buf_size);
  266.  
  267.     return 1;
  268.  
  269. fail:
  270.     av_freep(poutbuf);
  271.     *poutbuf_size = 0;
  272.     return ret;
  273. }
  274.  
  275. static void h264_mp4toannexb_filter_close(AVBitStreamFilterContext *bsfc)
  276. {
  277.     H264BSFContext *ctx = bsfc->priv_data;
  278.     if (ctx->private_spspps)
  279.         av_freep(&ctx->spspps_buf);
  280. }
  281.  
  282. AVBitStreamFilter ff_h264_mp4toannexb_bsf = {
  283.     .name           = "h264_mp4toannexb",
  284.     .priv_data_size = sizeof(H264BSFContext),
  285.     .filter         = h264_mp4toannexb_filter,
  286.     .close          = h264_mp4toannexb_filter_close,
  287. };
  288.