[FFmpeg-devel] [PATCH 1/3] avformat/mxfenc: H.264 Intra support

Michael Niedermayer michaelni at gmx.at
Mon Sep 15 13:12:39 CEST 2014


On Mon, Sep 15, 2014 at 10:26:28AM +0200, Robert Krüger wrote:
> On Sun, Sep 14, 2014 at 5:58 PM, Michael Niedermayer <michaelni at gmx.at> wrote:
> > On Sun, Sep 14, 2014 at 05:40:35PM +0200, Robert Krüger wrote:
> >> On Sat, Sep 13, 2014 at 12:36 PM, Michael Niedermayer <michaelni at gmx.at> wrote:
> >> > From: Baptiste Coudurier <baptiste.coudurier at gmail.com>
> >> >
> >> > Ported by michael from ffmbc to ffmpeg
> >> > the code is under CONFIG_GPL as ffmbc is GPL
> >> >
> >> > Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
> >> > ---
> >> >  libavformat/mxfenc.c |  143 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >> >  1 file changed, 143 insertions(+)
> >> >
> >> > diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
> >> > index 6a6b7c2..98f3479 100644
> >> > --- a/libavformat/mxfenc.c
> >> > +++ b/libavformat/mxfenc.c
> >> > @@ -40,6 +40,8 @@
> >> >  #include "libavutil/avassert.h"
> >> >  #include "libavcodec/bytestream.h"
> >> >  #include "libavcodec/dnxhddata.h"
> >> > +#include "libavcodec/h264.h"
> >> > +#include "libavcodec/internal.h"
> >> >  #include "audiointerleave.h"
> >> >  #include "avformat.h"
> >> >  #include "avio_internal.h"
> >> > @@ -95,6 +97,9 @@ static const struct {
> >> >      { AV_CODEC_ID_PCM_S16LE,  1 },
> >> >      { AV_CODEC_ID_DVVIDEO,   15 },
> >> >      { AV_CODEC_ID_DNXHD,     24 },
> >> > +#if CONFIG_GPL
> >> > +    { AV_CODEC_ID_H264,      34 },
> >> > +#endif
> >> >      { AV_CODEC_ID_NONE }
> >> >  };
> >> >
> >> > @@ -266,6 +271,13 @@ static const MXFContainerEssenceEntry mxf_essence_container_uls[] = {
> >> >        { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
> >> >        { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x13,0x00,0x00 },
> >> >        mxf_write_cdci_desc },
> >> > +#if CONFIG_GPL
> >> > +    // H.264
> >> > +    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x10,0x60,0x01 },
> >> > +      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
> >> > +      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x00,0x00,0x00 },
> >> > +      mxf_write_mpegvideo_desc },
> >> > +#endif // CONFIG_GPL
> >> >      { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
> >> >        { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
> >> >        { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
> >> > @@ -1564,6 +1576,130 @@ static int mxf_parse_dv_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt)
> >> >      return 1;
> >> >  }
> >> >
> >> > +#if CONFIG_GPL
> >> > +static const UID mxf_h264_codec_uls[] = {
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x30,0x00,0x00 }, // AVC Video
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x00,0x00 }, // AVC Intra
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x20,0x00 }, // AVC High 10 Intra
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x01 }, // AVC High 10 Intra RP2027 Class 50 1080/59.94i
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x02 }, // AVC High 10 Intra RP2027 Class 50 1080/50i
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x03 }, // AVC High 10 Intra RP2027 Class 50 1080/29.97p
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x04 }, // AVC High 10 Intra RP2027 Class 50 1080/25p
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x08 }, // AVC High 10 Intra RP2027 Class 50 720/59.94p
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x09 }, // AVC High 10 Intra RP2027 Class 50 720/50p
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x30,0x00 }, // AVC High 422 Intra
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x01 }, // AVC High 422 Intra RP2027 Class 100 1080/59.94i
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x02 }, // AVC High 422 Intra RP2027 Class 100 1080/50i
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x03 }, // AVC High 422 Intra RP2027 Class 100 1080/29.97p
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x04 }, // AVC High 422 Intra RP2027 Class 100 1080/25p
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x08 }, // AVC High 422 Intra RP2027 Class 100 720/59.94p
> >> > +    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x09 }, // AVC High 422 Intra RP2027 Class 100 720/50p
> >> > +};
> >> > +
> >> > +static const UID *mxf_get_h264_codec_ul(AVCodecContext *avctx, SPS *sps)
> >> > +{
> >> > +    int long_gop = avctx->gop_size > 1 || avctx->has_b_frames;
> >> > +
> >> > +    if ((sps->constraint_set_flags >> 3) & 1) {
> >> > +        if (sps->profile_idc == 110)
> >> > +            return &mxf_h264_codec_uls[2];
> >> > +        else if (sps->profile_idc == 122)
> >> > +            return &mxf_h264_codec_uls[9];
> >> > +    }
> >> > +    if (long_gop)
> >> > +        return &mxf_h264_codec_uls[0];
> >> > +    else
> >> > +        return &mxf_h264_codec_uls[1];
> >> > +}
> >> > +
> >> > +static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st,
> >> > +                                AVPacket *pkt, MXFIndexEntry *e)
> >> > +{
> >> > +    MXFStreamContext *sc = st->priv_data;
> >> > +    H264Context h;
> >> > +    const uint8_t *buf = pkt->data;
> >> > +    const uint8_t *buf_end = pkt->data + pkt->size;
> >> > +    uint32_t state = -1;
> >> > +    AVRational sar = {1, 1};
> >> > +
> >> > +    if (pkt->size < 5 || AV_RB32(pkt->data) != 0x0000001) {
> >> > +        av_log(s, AV_LOG_ERROR, "h264 bitstream malformated, "
> >> > +               "no startcode found, use -vbsf h264_mp4toannexb\n");
> >> > +        return 0;
> >> > +    }
> >> > +
> >> > +    memset(&h, 0, sizeof(h));
> >> > +    h.avctx = st->codec;
> >> > +    h.thread_context[0] = &h;
> >> > +    h.prev_frame_num = -1;
> >> > +
> >> > +    for (;;) {
> >> > +        int src_length, dst_length, consumed;
> >> > +        const uint8_t *ptr;
> >> > +
> >> > +        buf = avpriv_find_start_code(buf, buf_end, &state);
> >> > +        if (buf >= buf_end)
> >> > +            break;
> >> > +        --buf;
> >> > +        src_length = buf_end - buf;
> >> > +        switch (state & 0x1f) {
> >> > +        case NAL_SLICE:
> >> > +        case NAL_IDR_SLICE:
> >> > +            // Do not walk the whole buffer just to decode slice header
> >> > +            if (src_length > 20)
> >> > +                src_length = 20;
> >> > +            break;
> >> > +        }
> >> > +
> >> > +        ptr = ff_h264_decode_nal(&h, buf, &dst_length, &consumed, src_length);
> >> > +        if (!ptr || dst_length < 0)
> >> > +            break;
> >> > +
> >> > +        init_get_bits(&h.gb, ptr, 8*dst_length);
> >> > +        //av_log(avctx, AV_LOG_DEBUG, "nal_unit_type:%d\n", h.nal_unit_type);
> >> > +        switch (h.nal_unit_type) {
> >> > +        case NAL_SPS:
> >> > +            ff_h264_decode_seq_parameter_set(&h);
> >> > +            if (h.sps.sar.num > 0 && h.sps.sar.den > 0) {
> >> > +                sar.num = st->codec->width * h.sps.sar.num;
> >> > +                sar.den = st->codec->height * h.sps.sar.den;
> >> > +            }
> >> > +            sc->aspect_ratio.num = st->codec->width * sar.num;
> >> > +            sc->aspect_ratio.den = st->codec->height * sar.den;
> >> > +            av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den,
> >> > +                      sar.num, sar.den, 1024*1024);
> >> > +
> >> > +            sc->interlaced = !h.sps.frame_mbs_only_flag;
> >> > +            sc->component_depth = h.sps.bit_depth_luma;
> >> > +
> >> > +            sc->codec_ul = mxf_get_h264_codec_ul(st->codec, &h.sps);
> >> > +            e->flags |= 0x40;
> >> > +            break;
> >> > +        case NAL_PPS:
> >> > +            ff_h264_decode_picture_parameter_set(&h, h.gb.size_in_bits);
> >> > +            if (h.sps.timing_info_present_flag) {
> >> > +                if (st->codec->time_base.num != h.sps.num_units_in_tick ||
> >> > +                    st->codec->time_base.den*2 != h.sps.time_scale) {
> >> > +                    av_log(s, AV_LOG_ERROR, "framerate does not match bitstream values: %d/%d != %d/%d\n",
> >> > +                           h.sps.num_units_in_tick, h.sps.time_scale, st->codec->time_base.num, st->codec->time_base.den*2);
> >> > +                    return 0;
> >> > +                }
> >> > +            }
> >> > +            if (e->flags & 0x40) // sequence header present
> >> > +                e->flags |= 0x80; // random access
> >> > +            break;
> >> > +        case NAL_IDR_SLICE:
> >> > +            break;
> >> > +        case NAL_SLICE:
> >> > +            av_log(s, AV_LOG_ERROR, "mxf muxer only supports AVC Intra currently\n");
> >> > +            return 0;
> >> > +        }
> >> > +    }
> >> > +
> >> > +    return !!sc->codec_ul;
> >> > +}
> >> > +#endif // CONFIG_GPL
> >> > +
> >> >  static const UID mxf_mpeg2_codec_uls[] = {
> >> >      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x10,0x00 }, // MP-ML I-Frame
> >> >      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x11,0x00 }, // MP-ML Long GOP
> >> > @@ -1969,6 +2105,13 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
> >> >              av_log(s, AV_LOG_ERROR, "could not get dv profile\n");
> >> >              return -1;
> >> >          }
> >> > +#if CONFIG_GPL
> >> > +    } else if (st->codec->codec_id == AV_CODEC_ID_H264) {
> >> > +        if (!mxf_parse_h264_frame(s, st, pkt, &ie)) {
> >> > +            av_log(s, AV_LOG_ERROR, "could not get h264 profile and level\n");
> >> > +            return -1;
> >> > +        }
> >> > +#endif // CONFIG_GPL
> >> >      }
> >> >
> >> >      if (!mxf->header_written) {
> >> > --
> >> > 1.7.9.5
> >> >
> >>
> >> Just a general policy-question: will changes like this not in a way
> >> discourage development of these features in ffmpeg under LGPL? If
> >> someone now uses this code (e.g. mxf_parse_h264_frame) in other code
> >> they will have to make that GPL as well. In the long run this will
> >> make life harder for library users who cannot live with GPL. So far
> >> this hasn't been done on that level, at least not in the part of code
> >> that I am watching. AFAIR currently license borders are normally on a
> >> component level, i.e. a certain codec, format, filter only works only
> >> under GPL, not parts of functionality of a cocec, filter or muxer,
> >> which I think makes it OK to track by people for whom license matters.
> >> this extends this to a level where one would have to know which
> >> features of a certain muxer, codec, filter works under which license.
> >> Of course that's a project maintainer decision. Just wanted to throw
> >> in that side of the story, so it can be consciously taken into account
> >> or disregarded.
> >
> > This isnt the first "#if CONFIG_GPL" in the code.
> 
> Technically correct but I see only me_cmp.c and flac_dsp_init.c so far
> and I don't know what the code does better with GPL. So far I have not
> run into this as a library user and thus was not aware of it. At least
> it seems to be a rare exception. I am afraid of the situation it may
> create, if picking stuff from ffmbc and introducing it via #if
> CONFIG_GPL becomes more common.

I really think you are doing a "own goal" here

do you prefer if i do this work in a seperate branch outside FFmpeg
or what do you suggest ?

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

I do not agree with what you have to say, but I'll defend to the death your
right to say it. -- Voltaire
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20140915/905b5664/attachment.asc>


More information about the ffmpeg-devel mailing list