[FFmpeg-user] Custom data in AVPacket or AVFrame

laddoe xyfix at hotmail.com
Tue Feb 15 09:38:28 EET 2022


Hi,
I want to add a custom number to either an AVFame or an AVPacket before I encode it  and I want to retrieve it back when I decode it. I have tried using the AVFrame/AVPacket metadata or side_data but I guess I don't understand how to get it to work. I have also looked into  using AVDictionary/ AVDictionaryEntry  but nothing so far. The data that I want to store per frame is only a uint32_t. The encoding/decoding of frames work correctly, I have been running it for weeks, here is my encoding piece that suppose to add the "custom number" in, but I'm stuck ....

void MovieEncoder::writeFrame( AVFrame* frame, int frameNumber )
{
    int result;

    if ( s_frameCount >= streamNumberOfFrames)
        s_frameCount = streamNumberOfFrames;

    frame->pts = s_frameCount;

    if (m_formatCtx->oformat->flags & AVFMT_NOFILE )
    {
        AVPacket pkt;
        av_init_packet(&pkt);

        pkt.flags |= AV_PKT_FLAG_KEY;
        pkt.stream_index = m_stream->index;
        pkt.data = frame->data[0];
        pkt.size = sizeof(AVPicture);

        result = av_write_frame( m_formatCtx, &pkt );
    }
    else
    {
        AVPacket pkt;
        av_init_packet(&pkt);

        AVFrameSideData* numberSideData = av_frame_new_side_data( frame, AV_FRAME_DATA_GOP_TIMECODE, sizeof( uint64_t ))
//  Here the magic should happen, I think
        if( !numberSideData)
            return;

        result = avcodec_send_frame(m_codecCtx, frame);

        checkError( result, "Error encoding video frame: ");

        while( result >= 0 )
        {
            result = avcodec_receive_packet(m_codecCtx, &pkt);

            if (result == AVERROR(EAGAIN) /*|| ret == AVERROR_EOF*/)
            {
                Log::printLine("No more packet to write", Log::Debug );
                return;
            }
            else if (result < 0)
            {
                  Log::printLine("Codec context of the package is not correct", Log::Debug);
                  return;
            }

            pkt.stream_index = m_stream->index;

            pkt.pts = av_rescale_q( pkt.pts, m_codecCtx->time_base, m_stream->time_base );
            pkt.dts = av_rescale_q( pkt.dts, m_codecCtx->time_base, m_stream->time_base );

//            AVDictionary* dictionary = nullptr;
//            av_dict_set( &dictionary, metaKey.c_str(),std::to_string( frameNumber ).c_str(), 0 );

//            int dictionarySize = 0;
//            uint8_t* dictionaryData = av_packet_pack_dictionary( dictionary, &dictionarySize );

//            av_dict_free( &dictionary );

//            av_packet_add_side_data( &pkt, AV_PKT_DATA_STRINGS_METADATA, dictionaryData, dictionarySize );

            pkt.duration = int64( 1 / streamFrameRate );

            result = av_write_frame( m_formatCtx, &pkt );

            s_frameCount++;
        }
    }

//    av_dict_free( &dictionary );
}


More information about the ffmpeg-user mailing list