Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why do you use new Codec() object in examples? #96

Closed
suratovvlad opened this issue Aug 22, 2021 · 2 comments
Closed

Why do you use new Codec() object in examples? #96

suratovvlad opened this issue Aug 22, 2021 · 2 comments
Assignees
Labels

Comments

@suratovvlad
Copy link

suratovvlad commented Aug 22, 2021

Hello!
I am examining your project and decode/encode examples.

I found some strange places in the examples

Decode:

    if (vst.isValid()) {
        vdec = VideoDecoderContext(vst);
        vdec.setRefCountedFrames(true);

        vdec.open(Codec(), ec);
        if (ec) {
            cerr << "Can't open codec\n";
            return 1;
        }
    }

During initialization of VideoDecoderContext your code initializes Codec object and sets the code to the context

    } else {
        m_raw->codec_id   = !codec.isNull() ? codec.raw()->id : AV_CODEC_ID_NONE;
        m_raw->codec_type = type;
        m_raw->codec      = codec.raw();

        if (!codec.isNull()) {
            if (codec.raw()->pix_fmts != 0)
                m_raw->pix_fmt = *(codec.raw()->pix_fmts); // assign default value
            if (codec.raw()->sample_fmts != 0)
                m_raw->sample_fmt = *(codec.raw()->sample_fmts);
        }
    }

After that you call open() function with new object Codec().

However, in the example from ffmpeg documentation the codec initialized with avcodec_find_decoder is passed to the avcodec_open2.

The similar strange thing is with encode example:

    OutputFormat  ofrmt;
    FormatContext octx;

    ofrmt.setFormat(string(), out);
    octx.setFormat(ofrmt);

    Codec        ocodec  = findEncodingCodec(ofrmt);
    Stream      ost     = octx.addStream(ocodec);
    VideoEncoderContext encoder {ost};
....
    encoder.open(Codec(), ec);
    if (ec) {
        cerr << "Can't opent encodec\n";
        return 1;
    }

You create ocodec, but pass to encoder some new object.

Could you please explain why do you use uninitialized Codec object when you open decoder and encoder ?

@h4tr3d h4tr3d added the question label Dec 9, 2021
@h4tr3d h4tr3d self-assigned this Dec 9, 2021
@h4tr3d
Copy link
Owner

h4tr3d commented Dec 10, 2021

Hi,

All magic located here:

vdec = VideoDecoderContext(vst);

Just look into CodecContext2::CodecContext2(const Stream &st, const Codec &codec, Direction direction, AVMediaType type)

To simplify research, CodecContext2() called like:

CodecContext2(vst, Codec(), Direction::Decoding, AVMEDIA_TYPE_VIDEO)

Null Codec here means "use vst for the codec selection" and needed only for some corner cases, when codec overriding are needed:

... CodecContext2()...
...
    Codec c = codec;
    if (codec.isNull())
    {
        if (st.direction() == Direction::Decoding)
            c = findDecodingCodec(codecId);
        else
            c = findEncodingCodec(codecId);
    }
...

Open routine can be simplified to:

vdec.open(ec);

This mostly same to

vdec.open(Codec(), ec);

For opening this routine are used:

void CodecContext2::open(const Codec &codec, AVDictionary **options, OptionalErrorCode ec)
{
    clear_if(ec);

    if (isOpened() || !isValid()) {
        throws_if(ec, isOpened() ? Errors::CodecAlreadyOpened : Errors::CodecInvalid);
        return;
    }

    int stat = avcodec_open2(m_raw, codec.raw(), options);
    if (stat < 0)
        throws_if(ec, stat, ffmpeg_category());
}

You may be confused, that avcodec_open2() calls with NULL codec. But, look into avcodec_open2() description:

 * @param codec The codec to open this context for. If a non-NULL codec has been
 *              previously passed to avcodec_alloc_context3() or
 *              for this context, then this parameter MUST be either NULL or
 *              equal to the previously passed codec.

We are initialized VideoDecoderContext with the Stream reference. And already pass correct codec to the avcodec_alloc_context3(). So, now you have two ways:

  1. Add extra unuseful code to pass correct codec into open()
  2. Or just pass Empty/Null codec in to it )

@h4tr3d
Copy link
Owner

h4tr3d commented Dec 10, 2021

Ah! Codec() provides Null Codec :-)

And sorry for the long delay :-)

@h4tr3d h4tr3d closed this as completed Mar 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants