Recherche avancée

Médias (0)

Mot : - Tags -/flash

Aucun média correspondant à vos critères n’est disponible sur le site.

Autres articles (40)

  • La file d’attente de SPIPmotion

    28 novembre 2010, par

    Une file d’attente stockée dans la base de donnée
    Lors de son installation, SPIPmotion crée une nouvelle table dans la base de donnée intitulée spip_spipmotion_attentes.
    Cette nouvelle table est constituée des champs suivants : id_spipmotion_attente, l’identifiant numérique unique de la tâche à traiter ; id_document, l’identifiant numérique du document original à encoder ; id_objet l’identifiant unique de l’objet auquel le document encodé devra être attaché automatiquement ; objet, le type d’objet auquel (...)

  • Publier sur MédiaSpip

    13 juin 2013

    Puis-je poster des contenus à partir d’une tablette Ipad ?
    Oui, si votre Médiaspip installé est à la version 0.2 ou supérieure. Contacter au besoin l’administrateur de votre MédiaSpip pour le savoir

  • Contribute to documentation

    13 avril 2011

    Documentation is vital to the development of improved technical capabilities.
    MediaSPIP welcomes documentation by users as well as developers - including : critique of existing features and functions articles contributed by developers, administrators, content producers and editors screenshots to illustrate the above translations of existing documentation into other languages
    To contribute, register to the project users’ mailing (...)

Sur d’autres sites (7950)

  • How to reduce time while writing to output stream

    9 février 2021, par Summit

    I am streaming the render ouput of a opengl application using mpegts.The issue that i am facing is that the time taken to encode the frame is quite long.

    


    The application renders at 60 fps with frame size of 1920 X 1080 , the frame data of the application is pushed to a std::queue.

    


    This is the process for ffmpeg.

    


    I  initialize the stream like this.&#xA;&#xA;   streamerUpd.InitUPD("udp://127.0.0.1:1234", 1920, 1080, rings_);&#xA;&#xA;int StreamUPD::InitUPD(const char* url, int width, int height, std::shared_ptr<ringbuffer2> rings)&#xA;{&#xA;&#xA;    rings_ = rings;&#xA;    width_ = width;&#xA;    height_ = height;&#xA;    filename = url;&#xA;    int ret;&#xA;    av_dict_set(&amp;opt, "pkt_size", "1316", 0);&#xA;    &#xA;        &#xA;    avformat_alloc_output_context2(&amp;oc, nullptr, "mpegts", filename);&#xA;    if (!oc) {&#xA;        return 1;&#xA;    }&#xA;&#xA;    fmt = oc->oformat;&#xA;    /* Add the audio and video streams using the default format codecs&#xA;     * and initialize the codecs. */&#xA;    if (fmt->video_codec != AV_CODEC_ID_NONE) {&#xA;        add_stream(&amp;video_st, oc, &amp;video_codec, fmt->video_codec);&#xA;        have_video = 1;&#xA;        encode_video = 1;&#xA;    }&#xA;&#xA;    /* Write the stream header, if any. */&#xA;    ret = avformat_write_header(oc, &amp;opt);&#xA;    if (ret &lt; 0) {&#xA;        fprintf(stderr, "Error occurred when opening output file: %s\n",&#xA;            av_err2str(ret));&#xA;        return 1;&#xA;    }&#xA;    thr = std::thread(&amp;StreamUPD::output_result, this);&#xA;    return 0;&#xA;}&#xA;</ringbuffer2>

    &#xA;

    ////////////////////////////////////////////////////////////////////////////////////////

    &#xA;

    // Add the output stream

    &#xA;

    void StreamUPD::add_stream(OutputStream* ost, AVFormatContext* oc, AVCodec** codec, enum AVCodecID codec_id)&#xA;{&#xA;    AVCodecContext* c;&#xA;    int i;&#xA;    /* find the encoder */&#xA;    *codec = avcodec_find_encoder(codec_id);&#xA;    if (!(*codec)) {&#xA;        fprintf(stderr, "Could not find encoder for &#x27;%s&#x27;\n",&#xA;            avcodec_get_name(codec_id));&#xA;        exit(1);&#xA;    }&#xA;    ost->st = avformat_new_stream(oc, NULL);&#xA;    if (!ost->st) {&#xA;        fprintf(stderr, "Could not allocate stream\n");&#xA;        exit(1);&#xA;    }&#xA;    ost->st->id = oc->nb_streams - 1;&#xA;    c = avcodec_alloc_context3(*codec);&#xA;    if (!c) {&#xA;        fprintf(stderr, "Could not alloc an encoding context\n");&#xA;        exit(1);&#xA;    }&#xA;    ost->enc = c;&#xA;    switch ((*codec)->type) {&#xA;    case AVMEDIA_TYPE_VIDEO:&#xA;        c->codec_id = codec_id;&#xA;        c->bit_rate = 400000;&#xA;&#xA;        /* Resolution must be a multiple of two. */&#xA;        c->width = width_;&#xA;        c->height = height_;&#xA;        /* timebase: This is the fundamental unit of time (in seconds) in terms&#xA;         * of which frame timestamps are represented. For fixed-fps content,&#xA;         * timebase should be 1/framerate and timestamp increments should be&#xA;         * identical to 1. */&#xA;        ost->st->time_base = { 1, STREAM_FRAME_RATE };&#xA;        c->time_base = ost->st->time_base;&#xA;        c->gop_size = 12; /* emit one intra frame every twelve frames at most */&#xA;        c->pix_fmt = STREAM_PIX_FMT;&#xA;        &#xA;        if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {&#xA;            /* just for testing, we also add B-frames */&#xA;            qDebug() &lt;&lt; "This is MPEG2VIDEO Frame";&#xA;            c->max_b_frames = 2;&#xA;            &#xA;        }&#xA;        if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {&#xA;            /* Needed to avoid using macroblocks in which some coeffs overflow.&#xA;             * This does not happen with normal video, it just happens here as&#xA;             * the motion of the chroma plane does not match the luma plane. */&#xA;            c->mb_decision = 2;&#xA;        }&#xA;        break;&#xA;    default:&#xA;        break;&#xA;    }&#xA;    /* Some formats want stream headers to be separate. */&#xA;    if (oc->oformat->flags &amp; AVFMT_GLOBALHEADER)&#xA;        c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;&#xA;}&#xA;

    &#xA;

    //////////////////////////////////////////////////////////////////////////////////

    &#xA;

    // Open the video

    &#xA;

    void StreamUPD::open_video(AVFormatContext* oc, AVCodec* codec, OutputStream* ost, AVDictionary* opt_arg)&#xA;    {&#xA;        int ret;&#xA;        AVCodecContext* c = ost->enc;&#xA;        AVDictionary* opt = NULL;&#xA;        av_dict_copy(&amp;opt, opt_arg, 0);&#xA;        /* open the codec */&#xA;        ret = avcodec_open2(c, codec, &amp;opt);&#xA;        av_dict_free(&amp;opt);&#xA;        if (ret &lt; 0) {&#xA;            fprintf(stderr, "Could not open video codec: %s\n", av_err2str(ret));&#xA;            exit(1);&#xA;        }&#xA;        /* allocate and init a re-usable frame */&#xA;        ost->frame = alloc_picture(c->pix_fmt, c->width, c->height);&#xA;        if (!ost->frame) {&#xA;            fprintf(stderr, "Could not allocate video frame\n");&#xA;            exit(1);&#xA;        }&#xA;        /* If the output format is not YUV420P, then a temporary YUV420P&#xA;         * picture is needed too. It is then converted to the required&#xA;         * output format. */&#xA;        ost->tmp_frame = NULL;&#xA;        if (c->pix_fmt != AV_PIX_FMT_YUV420P) {&#xA;            ost->tmp_frame = alloc_picture(AV_PIX_FMT_YUV420P, c->width, c->height);&#xA;            if (!ost->tmp_frame) {&#xA;                fprintf(stderr, "Could not allocate temporary picture\n");&#xA;                exit(1);&#xA;            }&#xA;        }&#xA;        /* copy the stream parameters to the muxer */&#xA;        ret = avcodec_parameters_from_context(ost->st->codecpar, c);&#xA;        if (ret &lt; 0) {&#xA;            fprintf(stderr, "Could not copy the stream parameters\n");&#xA;            exit(1);&#xA;        }&#xA;    }&#xA;

    &#xA;

    Once i have setup the ffmpeg output stream this is how i am streaming the data.

    &#xA;

    This function gets the frame data from the std::queue(pixelsQueue) and sends it for encoding.

    &#xA;

    int StreamUPD::stream_video_frame()&#xA;{   &#xA;    ost = &amp;video_st;&#xA;    c = ost->enc;   &#xA;&#xA;    /* when we pass a frame to the encoder, it may keep a reference to it&#xA;     * internally; make sure we do not overwrite it here */&#xA;    if (av_frame_make_writable(ost->frame) &lt; 0)&#xA;        exit(1);&#xA;    if (!ost->sws_ctx) {&#xA;        ost->sws_ctx = sws_getContext(c->width, c->height,&#xA;            AV_PIX_FMT_RGB24,&#xA;            c->width, c->height,&#xA;            c->pix_fmt,&#xA;            SWS_FAST_BILINEAR, NULL, NULL, NULL);&#xA;        if (!ost->sws_ctx) {&#xA;            fprintf(stderr,&#xA;                "Could not initialize the conversion context\n");&#xA;            exit(1);&#xA;        }&#xA;    }&#xA;    finished_ = true;&#xA;&#xA;    if (pixelsQueue.size() > 0) {       &#xA;        if (pixelsQueue.pop(pixels)) {&#xA;            fill_yuv_image(ost->sws_ctx, frame_data->pixels_.get(), ost->frame, c->width, c->height);&#xA;            ost->frame->pts = ost->next_pts&#x2B;&#x2B;;&#xA;            return write_frame(oc, ost->enc, ost->st, ost->frame);&#xA;        }&#xA;    }&#xA;    return 1;&#xA;}&#xA;

    &#xA;

    Writing the data to the output stream.

    &#xA;

    The function avcodec_receive_packet is the one that takes lot of time.

    &#xA;

    int StreamUPD::write_frame(AVFormatContext* fmt_ctx, AVCodecContext* c,&#xA;    AVStream* st, AVFrame* frame)&#xA;{&#xA;    int ret;&#xA;    // send the frame to the encoder&#xA;    AVPacket pkt = { 0 };&#xA;    ret = avcodec_send_frame(c, frame);&#xA;    ret = avcodec_receive_packet(c, &amp;pkt);&#xA;    if (ret &lt; 0) {&#xA;        fprintf(stderr, "Error sending a frame to the encoder: %s\n",&#xA;            av_err2str(ret));&#xA;        exit(1);&#xA;    }&#xA;    &#xA;    while (ret >= 0) {&#xA;        AVPacket pkt = { 0 };&#xA;        ret = avcodec_receive_packet(c, &amp;pkt);  // This is the function that takes lot of time&#xA;        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)&#xA;            break;&#xA;        else if (ret &lt; 0) {&#xA;            fprintf(stderr, "Error encoding a frame: %s\n", av_err2str(ret));&#xA;            exit(1);&#xA;        }&#xA;        // rescale output packet timestamp values from codec to stream timebase &#xA;        av_packet_rescale_ts(&amp;pkt, c->time_base, st->time_base);&#xA;        pkt.stream_index = st->index;&#xA;        // Write the compressed frame to the media file. &#xA;        ret = av_interleaved_write_frame(fmt_ctx, &amp;pkt);&#xA;        av_packet_unref(&amp;pkt);&#xA;        if (ret &lt; 0) {&#xA;            fprintf(stderr, "Error while writing output packet: %s\n", av_err2str(ret));&#xA;            exit(1);&#xA;        }&#xA;    }&#xA;    return ret == AVERROR_EOF ? 1 : 0;&#xA;}&#xA;

    &#xA;

    How can i reduce the outputting time while writing the frames to the stream ?

    &#xA;

    Currently i push more frames in the buffer and the outputting speed is less so the buffer starts to run out of memory in some time.

    &#xA;

  • Encoding .png images with h264 to a file on disk

    19 février 2021, par xyfix

    Can somebody help me to find out why I end up with a file on disk that is only 24 kb and not readable by vlc or so, while I send valid YUV images to the codec. I have added the .h and .cpp file. Up till "avcodec_receive_packet" everything seems to be OK. The function call "avcodec_send_frame" returns 0, so that must be OK but "avcodec_receive_packet" returns -11. If I flush the encoder (currently commented) then "avcodec_receive_packet" returns 0 and I can see encoded data if I store it on disk. Also the input image to the encoder is also correct (currently commented) and checked. I'm aiming for an intra-frame encoding, so I should get the encoded frame data back, but I don't get anything back even if I send 24 images to it.

    &#xA;

    .h file

    &#xA;

    #ifndef MOVIECODEC_H&#xA;#define MOVIECODEC_H&#xA;&#xA;#include &#xA;&#xA;extern "C"&#xA;{&#xA;    #include "Codec/include/libavcodec/avcodec.h"&#xA;    #include "Codec/include/libavdevice/avdevice.h"&#xA;    #include "Codec/include/libavformat/avformat.h"&#xA;    #include "Codec/include/libavutil/avutil.h"&#xA;    #include "Codec/include/libavutil/imgutils.h"&#xA;    #include "Codec/include/libswscale/swscale.h"&#xA;}&#xA;&#xA;&#xA;class MovieCodec&#xA;{&#xA;public:&#xA;&#xA;    MovieCodec(const char *filename);&#xA;&#xA;    ~MovieCodec();&#xA;&#xA;    void encodeImage( const cv::Mat&amp; image );&#xA;&#xA;    void close();&#xA;    &#xA;private :&#xA;&#xA;    void add_stream();&#xA;&#xA;    void openVideoCodec();&#xA;&#xA;    void write_video_frame(const cv::Mat&amp; image);&#xA;&#xA;    void createFrame( const cv::Mat&amp; image );&#xA;&#xA;private:&#xA;&#xA;    static int s_frameCount;&#xA;&#xA;    int m_timeVideo = 0;&#xA;&#xA;    std::string m_filename;&#xA;&#xA;    FILE* m_file;&#xA;&#xA;    AVCodec* m_encoder = NULL;&#xA;&#xA;    AVOutputFormat* m_outputFormat = NULL;&#xA;&#xA;    AVFormatContext* m_formatCtx = NULL;&#xA;&#xA;    AVCodecContext* m_codecCtx = NULL;&#xA;&#xA;    AVStream* m_streamOut = NULL;&#xA;&#xA;    AVFrame* m_frame = NULL;&#xA;&#xA;    AVPacket* m_packet = NULL;&#xA;&#xA;};&#xA;

    &#xA;

    .cpp file

    &#xA;

    #ifndef MOVIECODEC_CPP&#xA;#define MOVIECODEC_CPP&#xA;&#xA;#include "moviecodec.h"&#xA;&#xA;&#xA;#define STREAM_DURATION   5.0&#xA;#define STREAM_FRAME_RATE 24&#xA;#define STREAM_NB_FRAMES  ((int)(STREAM_DURATION * STREAM_FRAME_RATE))&#xA;#define STREAM_PIX_FMT    AV_PIX_FMT_YUV420P /* default pix_fmt */&#xA;&#xA;&#xA;static int sws_flags = SWS_BICUBIC;&#xA;int MovieCodec::s_frameCount = 0;&#xA;&#xA;MovieCodec::MovieCodec( const char* filename ) :&#xA;    m_filename( filename ),&#xA;    m_encoder( avcodec_find_encoder( AV_CODEC_ID_H264 ))&#xA;{&#xA;    av_log_set_level(AV_LOG_VERBOSE);&#xA;&#xA;    int ret(0);&#xA;&#xA;    m_file = fopen( m_filename.c_str(), "wb");&#xA;&#xA;    // allocate the output media context&#xA;    ret = avformat_alloc_output_context2( &amp;m_formatCtx, m_outputFormat, NULL, m_filename.c_str());&#xA;&#xA;    if (!m_formatCtx)&#xA;        return;&#xA;&#xA;    m_outputFormat = m_formatCtx->oformat;&#xA;&#xA;    // Add the video stream using H264 codec&#xA;    add_stream();&#xA;&#xA;    // Open video codec and allocate the necessary encode buffers&#xA;    if (m_streamOut)&#xA;        openVideoCodec();&#xA;&#xA;    av_dump_format( m_formatCtx, 0, m_filename.c_str(), 1);&#xA;&#xA;    // Open the output media file, if needed&#xA;    if (!( m_outputFormat->flags &amp; AVFMT_NOFILE))&#xA;    {&#xA;        ret = avio_open( &amp;m_formatCtx->pb, m_filename.c_str(), AVIO_FLAG_WRITE);&#xA;&#xA;        if (ret &lt; 0)&#xA;        {&#xA;            char error[255];&#xA;            ret = av_strerror( ret, error, 255);&#xA;            fprintf(stderr, "Could not open &#x27;%s&#x27;: %s\n", m_filename.c_str(), error);&#xA;            return ;&#xA;        }&#xA;    }&#xA;    else&#xA;    {&#xA;        return;&#xA;    }&#xA;&#xA;    m_formatCtx->flush_packets = 1;&#xA;&#xA;    ret = avformat_write_header( m_formatCtx, NULL );&#xA;&#xA;    if (ret &lt; 0)&#xA;    {&#xA;        char error[255];&#xA;        av_strerror(ret, error, 255);&#xA;        fprintf(stderr, "Error occurred when opening output file: %s\n", error);&#xA;        return;&#xA;    }&#xA;&#xA;&#xA;    if ( m_frame )&#xA;           m_frame->pts = 0;&#xA;}&#xA;&#xA;&#xA;&#xA;MovieCodec::~MovieCodec()&#xA;{&#xA;    close();&#xA;}&#xA;&#xA;&#xA;&#xA;void MovieCodec::encodeImage(const cv::Mat &amp;image)&#xA;{&#xA;    // Compute video time from last added video frame&#xA;    m_timeVideo = (double)m_frame->pts) * av_q2d(m_streamOut->time_base);&#xA;&#xA;    // Stop media if enough time&#xA;    if (!m_streamOut /*|| m_timeVideo >= STREAM_DURATION*/)&#xA;       return;&#xA;&#xA;    // Add a video frame&#xA;    write_video_frame( image );&#xA;&#xA;    // Increase frame pts according to time base&#xA;    m_frame->pts &#x2B;= av_rescale_q(1, m_codecCtx->time_base, m_streamOut->time_base);&#xA;}&#xA;&#xA;&#xA;void MovieCodec::close()&#xA;{&#xA;    int ret( 0 );&#xA;&#xA;    // Write media trailer&#xA;//    if( m_formatCtx )&#xA;//        ret = av_write_trailer( m_formatCtx );&#xA;&#xA;    /* flush the encoder */&#xA;    ret = avcodec_send_frame(m_codecCtx, NULL);&#xA;&#xA;    /* Close each codec. */&#xA;    if ( m_streamOut )&#xA;    {&#xA;        av_free( m_frame->data[0]);&#xA;        av_free( m_frame );&#xA;    }&#xA;&#xA;    if (!( m_outputFormat->flags &amp; AVFMT_NOFILE))&#xA;        /* Close the output file. */&#xA;        ret = avio_close( m_formatCtx->pb);&#xA;&#xA;&#xA;    /* free the stream */&#xA;    avformat_free_context( m_formatCtx );&#xA;&#xA;    fflush( m_file );&#xA;}&#xA;&#xA;&#xA;void MovieCodec::createFrame( const cv::Mat&amp; image )&#xA;{&#xA;    /**&#xA;     * \note allocate frame&#xA;     */&#xA;    m_frame = av_frame_alloc();&#xA;    m_frame->format = STREAM_PIX_FMT;&#xA;    m_frame->width = image.cols();&#xA;    m_frame->height = image.rows();&#xA;    m_frame->pict_type = AV_PICTURE_TYPE_I;&#xA;    int ret = av_image_alloc(m_frame->data, m_frame->linesize, m_frame->width,  m_frame->height, STREAM_PIX_FMT, 1);&#xA;&#xA;    if (ret &lt; 0)&#xA;    {&#xA;        return;&#xA;    }&#xA;&#xA;    struct SwsContext* sws_ctx = sws_getContext((int)image.cols(), (int)image.rows(), AV_PIX_FMT_RGB24,&#xA;                                                (int)image.cols(), (int)image.rows(), STREAM_PIX_FMT, 0, NULL, NULL, NULL);&#xA;&#xA;    const uint8_t* rgbData[1] = { (uint8_t* )image.getData() };&#xA;    int rgbLineSize[1] = { 3 * image.cols() };&#xA;&#xA;    sws_scale(sws_ctx, rgbData, rgbLineSize, 0, image.rows(), m_frame->data, m_frame->linesize);&#xA;}&#xA;&#xA;&#xA;/* Add an output stream. */&#xA;void MovieCodec::add_stream()&#xA;{&#xA;    AVCodecID codecId = AV_CODEC_ID_H264;&#xA;&#xA;    if (!( m_encoder ))&#xA;    {&#xA;        fprintf(stderr, "Could not find encoder for &#x27;%s&#x27;\n",&#xA;            avcodec_get_name(codecId));&#xA;        return;&#xA;    }&#xA;&#xA;    // Get the stream for codec&#xA;    m_streamOut = avformat_new_stream(m_formatCtx, m_encoder);&#xA;&#xA;    if (!m_streamOut) {&#xA;        fprintf(stderr, "Could not allocate stream\n");&#xA;        return;&#xA;    }&#xA;&#xA;    m_streamOut->id = m_formatCtx->nb_streams - 1;&#xA;&#xA;    m_codecCtx = avcodec_alloc_context3( m_encoder);&#xA;&#xA;    m_streamOut->codecpar->codec_id = codecId;&#xA;    m_streamOut->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;&#xA;    m_streamOut->codecpar->bit_rate = 400000;&#xA;    m_streamOut->codecpar->width = 800;&#xA;    m_streamOut->codecpar->height = 640;&#xA;    m_streamOut->codecpar->format = STREAM_PIX_FMT;&#xA;    m_streamOut->codecpar->codec_tag = 0x31637661;&#xA;    m_streamOut->codecpar->video_delay = 0;&#xA;    m_streamOut->time_base = { 1, STREAM_FRAME_RATE };&#xA;&#xA;&#xA;    avcodec_parameters_to_context( m_codecCtx, m_streamOut->codecpar);&#xA;    &#xA;    m_codecCtx->gop_size = 0; /* emit one intra frame every twelve frames at most */&#xA;    m_codecCtx->max_b_frames = 0;&#xA;    m_codecCtx->time_base = { 1, STREAM_FRAME_RATE };&#xA;    m_codecCtx->framerate = { STREAM_FRAME_RATE, 1 };&#xA;    m_codecCtx->pix_fmt = STREAM_PIX_FMT;&#xA;&#xA;&#xA;&#xA;    if (m_streamOut->codecpar->codec_id == AV_CODEC_ID_H264)&#xA;    {&#xA;      av_opt_set( m_codecCtx, "preset", "ultrafast", 0 );&#xA;      av_opt_set( m_codecCtx, "vprofile", "baseline", 0 );&#xA;      av_opt_set( m_codecCtx, "tune", "zerolatency", 0 );&#xA;    }&#xA;&#xA;//    /* Some formats want stream headers to be separate. */&#xA;//    if (m_formatCtx->oformat->flags &amp; AVFMT_GLOBALHEADER)&#xA;//            m_codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;&#xA;&#xA;&#xA;}&#xA;&#xA;&#xA;void MovieCodec::openVideoCodec()&#xA;{&#xA;    int ret;&#xA;&#xA;    /* open the codec */&#xA;    ret = avcodec_open2(m_codecCtx, m_encoder, NULL);&#xA;&#xA;    if (ret &lt; 0)&#xA;    {&#xA;        char error[255];&#xA;        av_strerror(ret, error, 255);&#xA;        fprintf(stderr, "Could not open video codec: %s\n", error);&#xA;    }&#xA;}&#xA;&#xA;&#xA;&#xA;void MovieCodec::write_video_frame( const cv::Mat&amp; image )&#xA;{&#xA;    int ret;&#xA;&#xA;    createFrame( image );&#xA;&#xA;&#xA;    if (m_formatCtx->oformat->flags &amp; 0x0020 )&#xA;    {&#xA;        /* Raw video case - directly store the picture in the packet */&#xA;        AVPacket pkt;&#xA;        av_init_packet(&amp;pkt);&#xA;&#xA;        pkt.flags |= AV_PKT_FLAG_KEY;&#xA;        pkt.stream_index = m_streamOut->index;&#xA;        pkt.data = m_frame->data[0];&#xA;        pkt.size = sizeof(AVPicture);&#xA;&#xA;//        ret = av_interleaved_write_frame(m_formatCtx, &amp;pkt);&#xA;        ret = av_write_frame( m_formatCtx, &amp;pkt );&#xA;    }&#xA;    else&#xA;    {&#xA;        AVPacket pkt;&#xA;        av_init_packet(&amp;pkt);&#xA;&#xA;        /* encode the image */&#xA;&#xA;//cv::Mat yuv420p( m_frame->height &#x2B; m_frame->height/2, m_frame->width, CV_8UC1, m_frame->data[0]);&#xA;//cv::Mat cvmIm;&#xA;//cv::cvtColor(yuv420p,cvmIm,CV_YUV420p2BGR);&#xA;//cv::imwrite("c:\\tmp\\YUVoriginal.png", cvmIm);&#xA;&#xA;        ret = avcodec_send_frame(m_codecCtx, m_frame);&#xA;&#xA;        if (ret &lt; 0)&#xA;        {&#xA;            char error[255];&#xA;            av_strerror(ret, error, 255);&#xA;            fprintf(stderr, "Error encoding video frame: %s\n", error);&#xA;            return;&#xA;        }&#xA;&#xA;        /* If size is zero, it means the image was buffered. */&#xA;//        ret = avcodec_receive_packet(m_codecCtx, &amp;pkt);&#xA;&#xA;        do&#xA;        {&#xA;            ret = avcodec_receive_packet(m_codecCtx, &amp;pkt);&#xA;&#xA;            if (ret == 0)&#xA;            {&#xA;                ret = av_write_frame( m_formatCtx, &amp;pkt );&#xA;                av_packet_unref(&amp;pkt);&#xA;&#xA;                break;&#xA;            }&#xA;//            else if ((ret &lt; 0) &amp;&amp; (ret != AVERROR(EAGAIN)))&#xA;//            {&#xA;//                return;&#xA;//            }&#xA;//            else if (ret == AVERROR(EAGAIN))&#xA;//            {&#xA;//                /* flush the encoder */&#xA;//                ret = avcodec_send_frame(m_codecCtx, NULL);&#xA;//&#xA;//                if (0 > ret)&#xA;//                    return;&#xA;//            }&#xA;        } while (ret == 0);&#xA;&#xA;        if( !ret &amp;&amp; pkt.size)&#xA;        {&#xA;            pkt.stream_index = m_streamOut->index;&#xA;&#xA;            /* Write the compressed frame to the media file. */&#xA;//            ret = av_interleaved_write_frame(m_formatCtx, &amp;pkt);&#xA;            ret = av_write_frame( m_formatCtx, &amp;pkt );&#xA;        }&#xA;        else&#xA;        {&#xA;            ret = 0;&#xA;        }&#xA;    }&#xA;&#xA;    if (ret != 0)&#xA;    {&#xA;        char error[255];&#xA;        av_strerror(ret, error, 255);&#xA;        fprintf(stderr, "Error while writing video frame: %s\n", error);&#xA;        return;&#xA;    }&#xA;&#xA;    s_frameCount&#x2B;&#x2B;;&#xA;}&#xA;

    &#xA;

  • Encoding .png images with h264 to a file on disk

    21 février 2021, par xyfix

    Can somebody help me to find out why I end up with a file on disk that is only 24 kb and not readable by vlc or so, while I send valid YUV images to the codec. I have added the .h and .cpp file. Up till "avcodec_receive_packet" everything seems to be OK. The function call "avcodec_send_frame" returns 0, so that must be OK but "avcodec_receive_packet" returns -11. If I flush the encoder (currently commented) then "avcodec_receive_packet" returns 0 and I can see encoded data if I store it on disk. Also the input image to the encoder is also correct (currently commented) and checked. I'm aiming for an intra-frame encoding, so I should get the encoded frame data back, but I don't get anything back even if I send 24 images to it.

    &#xA;

    .h file

    &#xA;

    #ifndef MOVIECODEC_H&#xA;#define MOVIECODEC_H&#xA;&#xA;#include &#xA;&#xA;extern "C"&#xA;{&#xA;    #include "Codec/include/libavcodec/avcodec.h"&#xA;    #include "Codec/include/libavdevice/avdevice.h"&#xA;    #include "Codec/include/libavformat/avformat.h"&#xA;    #include "Codec/include/libavutil/avutil.h"&#xA;    #include "Codec/include/libavutil/imgutils.h"&#xA;    #include "Codec/include/libswscale/swscale.h"&#xA;}&#xA;&#xA;&#xA;class MovieCodec&#xA;{&#xA;public:&#xA;&#xA;    MovieCodec(const char *filename);&#xA;&#xA;    ~MovieCodec();&#xA;&#xA;    void encodeImage( const cv::Mat&amp; image );&#xA;&#xA;    void close();&#xA;    &#xA;private :&#xA;&#xA;    void add_stream();&#xA;&#xA;    void openVideoCodec();&#xA;&#xA;    void write_video_frame(const cv::Mat&amp; image);&#xA;&#xA;    void createFrame( const cv::Mat&amp; image );&#xA;&#xA;private:&#xA;&#xA;    static int s_frameCount;&#xA;&#xA;    int m_timeVideo = 0;&#xA;&#xA;    std::string m_filename;&#xA;&#xA;    FILE* m_file;&#xA;&#xA;    AVCodec* m_encoder = NULL;&#xA;&#xA;    AVOutputFormat* m_outputFormat = NULL;&#xA;&#xA;    AVFormatContext* m_formatCtx = NULL;&#xA;&#xA;    AVCodecContext* m_codecCtx = NULL;&#xA;&#xA;    AVStream* m_streamOut = NULL;&#xA;&#xA;    AVFrame* m_frame = NULL;&#xA;&#xA;    AVPacket* m_packet = NULL;&#xA;&#xA;};&#xA;

    &#xA;

    .cpp file

    &#xA;

    #ifndef MOVIECODEC_CPP&#xA;#define MOVIECODEC_CPP&#xA;&#xA;#include "moviecodec.h"&#xA;&#xA;&#xA;#define STREAM_DURATION   5.0&#xA;#define STREAM_FRAME_RATE 24&#xA;#define STREAM_NB_FRAMES  ((int)(STREAM_DURATION * STREAM_FRAME_RATE))&#xA;#define STREAM_PIX_FMT    AV_PIX_FMT_YUV420P /* default pix_fmt */&#xA;&#xA;&#xA;static int sws_flags = SWS_BICUBIC;&#xA;int MovieCodec::s_frameCount = 0;&#xA;&#xA;MovieCodec::MovieCodec( const char* filename ) :&#xA;    m_filename( filename ),&#xA;    m_encoder( avcodec_find_encoder( AV_CODEC_ID_H264 ))&#xA;{&#xA;    av_log_set_level(AV_LOG_VERBOSE);&#xA;&#xA;    int ret(0);&#xA;&#xA;    m_file = fopen( m_filename.c_str(), "wb");&#xA;&#xA;    // allocate the output media context&#xA;    ret = avformat_alloc_output_context2( &amp;m_formatCtx, m_outputFormat, NULL, m_filename.c_str());&#xA;&#xA;    if (!m_formatCtx)&#xA;        return;&#xA;&#xA;    m_outputFormat = m_formatCtx->oformat;&#xA;&#xA;    // Add the video stream using H264 codec&#xA;    add_stream();&#xA;&#xA;    // Open video codec and allocate the necessary encode buffers&#xA;    if (m_streamOut)&#xA;        openVideoCodec();&#xA;&#xA;    av_dump_format( m_formatCtx, 0, m_filename.c_str(), 1);&#xA;&#xA;    // Open the output media file, if needed&#xA;    if (!( m_outputFormat->flags &amp; AVFMT_NOFILE))&#xA;    {&#xA;        ret = avio_open( &amp;m_formatCtx->pb, m_filename.c_str(), AVIO_FLAG_WRITE);&#xA;&#xA;        if (ret &lt; 0)&#xA;        {&#xA;            char error[255];&#xA;            ret = av_strerror( ret, error, 255);&#xA;            fprintf(stderr, "Could not open &#x27;%s&#x27;: %s\n", m_filename.c_str(), error);&#xA;            return ;&#xA;        }&#xA;    }&#xA;    else&#xA;    {&#xA;        return;&#xA;    }&#xA;&#xA;    m_formatCtx->flush_packets = 1;&#xA;&#xA;    ret = avformat_write_header( m_formatCtx, NULL );&#xA;&#xA;    if (ret &lt; 0)&#xA;    {&#xA;        char error[255];&#xA;        av_strerror(ret, error, 255);&#xA;        fprintf(stderr, "Error occurred when opening output file: %s\n", error);&#xA;        return;&#xA;    }&#xA;&#xA;&#xA;    if ( m_frame )&#xA;           m_frame->pts = 0;&#xA;}&#xA;&#xA;&#xA;&#xA;MovieCodec::~MovieCodec()&#xA;{&#xA;    close();&#xA;}&#xA;&#xA;&#xA;&#xA;void MovieCodec::encodeImage(const cv::Mat &amp;image)&#xA;{&#xA;    // Compute video time from last added video frame&#xA;    m_timeVideo = (double)m_frame->pts) * av_q2d(m_streamOut->time_base);&#xA;&#xA;    // Stop media if enough time&#xA;    if (!m_streamOut /*|| m_timeVideo >= STREAM_DURATION*/)&#xA;       return;&#xA;&#xA;    // Add a video frame&#xA;    write_video_frame( image );&#xA;&#xA;    // Increase frame pts according to time base&#xA;    m_frame->pts &#x2B;= av_rescale_q(1, m_codecCtx->time_base, m_streamOut->time_base);&#xA;}&#xA;&#xA;&#xA;void MovieCodec::close()&#xA;{&#xA;    int ret( 0 );&#xA;&#xA;    // Write media trailer&#xA;//    if( m_formatCtx )&#xA;//        ret = av_write_trailer( m_formatCtx );&#xA;&#xA;    /* flush the encoder */&#xA;    ret = avcodec_send_frame(m_codecCtx, NULL);&#xA;&#xA;    /* Close each codec. */&#xA;    if ( m_streamOut )&#xA;    {&#xA;        av_free( m_frame->data[0]);&#xA;        av_free( m_frame );&#xA;    }&#xA;&#xA;    if (!( m_outputFormat->flags &amp; AVFMT_NOFILE))&#xA;        /* Close the output file. */&#xA;        ret = avio_close( m_formatCtx->pb);&#xA;&#xA;&#xA;    /* free the stream */&#xA;    avformat_free_context( m_formatCtx );&#xA;&#xA;    fflush( m_file );&#xA;}&#xA;&#xA;&#xA;void MovieCodec::createFrame( const cv::Mat&amp; image )&#xA;{&#xA;    /**&#xA;     * \note allocate frame&#xA;     */&#xA;    m_frame = av_frame_alloc();&#xA;    m_frame->format = STREAM_PIX_FMT;&#xA;    m_frame->width = image.cols();&#xA;    m_frame->height = image.rows();&#xA;    m_frame->pict_type = AV_PICTURE_TYPE_I;&#xA;    int ret = av_image_alloc(m_frame->data, m_frame->linesize, m_frame->width,  m_frame->height, STREAM_PIX_FMT, 1);&#xA;&#xA;    if (ret &lt; 0)&#xA;    {&#xA;        return;&#xA;    }&#xA;&#xA;    struct SwsContext* sws_ctx = sws_getContext((int)image.cols(), (int)image.rows(), AV_PIX_FMT_RGB24,&#xA;                                                (int)image.cols(), (int)image.rows(), STREAM_PIX_FMT, 0, NULL, NULL, NULL);&#xA;&#xA;    const uint8_t* rgbData[1] = { (uint8_t* )image.getData() };&#xA;    int rgbLineSize[1] = { 3 * image.cols() };&#xA;&#xA;    sws_scale(sws_ctx, rgbData, rgbLineSize, 0, image.rows(), m_frame->data, m_frame->linesize);&#xA;}&#xA;&#xA;&#xA;/* Add an output stream. */&#xA;void MovieCodec::add_stream()&#xA;{&#xA;    AVCodecID codecId = AV_CODEC_ID_H264;&#xA;&#xA;    if (!( m_encoder ))&#xA;    {&#xA;        fprintf(stderr, "Could not find encoder for &#x27;%s&#x27;\n",&#xA;            avcodec_get_name(codecId));&#xA;        return;&#xA;    }&#xA;&#xA;    // Get the stream for codec&#xA;    m_streamOut = avformat_new_stream(m_formatCtx, m_encoder);&#xA;&#xA;    if (!m_streamOut) {&#xA;        fprintf(stderr, "Could not allocate stream\n");&#xA;        return;&#xA;    }&#xA;&#xA;    m_streamOut->id = m_formatCtx->nb_streams - 1;&#xA;&#xA;    m_codecCtx = avcodec_alloc_context3( m_encoder);&#xA;&#xA;    m_streamOut->codecpar->codec_id = codecId;&#xA;    m_streamOut->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;&#xA;    m_streamOut->codecpar->bit_rate = 400000;&#xA;    m_streamOut->codecpar->width = 800;&#xA;    m_streamOut->codecpar->height = 640;&#xA;    m_streamOut->codecpar->format = STREAM_PIX_FMT;&#xA;    m_streamOut->codecpar->codec_tag = 0x31637661;&#xA;    m_streamOut->codecpar->video_delay = 0;&#xA;    m_streamOut->time_base = { 1, STREAM_FRAME_RATE };&#xA;&#xA;&#xA;    avcodec_parameters_to_context( m_codecCtx, m_streamOut->codecpar);&#xA;    &#xA;    m_codecCtx->gop_size = 0; /* emit one intra frame every twelve frames at most */&#xA;    m_codecCtx->max_b_frames = 0;&#xA;    m_codecCtx->time_base = { 1, STREAM_FRAME_RATE };&#xA;    m_codecCtx->framerate = { STREAM_FRAME_RATE, 1 };&#xA;    m_codecCtx->pix_fmt = STREAM_PIX_FMT;&#xA;&#xA;&#xA;&#xA;    if (m_streamOut->codecpar->codec_id == AV_CODEC_ID_H264)&#xA;    {&#xA;      av_opt_set( m_codecCtx, "preset", "ultrafast", 0 );&#xA;      av_opt_set( m_codecCtx, "vprofile", "baseline", 0 );&#xA;      av_opt_set( m_codecCtx, "tune", "zerolatency", 0 );&#xA;    }&#xA;&#xA;//    /* Some formats want stream headers to be separate. */&#xA;//    if (m_formatCtx->oformat->flags &amp; AVFMT_GLOBALHEADER)&#xA;//            m_codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;&#xA;&#xA;&#xA;}&#xA;&#xA;&#xA;void MovieCodec::openVideoCodec()&#xA;{&#xA;    int ret;&#xA;&#xA;    /* open the codec */&#xA;    ret = avcodec_open2(m_codecCtx, m_encoder, NULL);&#xA;&#xA;    if (ret &lt; 0)&#xA;    {&#xA;        char error[255];&#xA;        av_strerror(ret, error, 255);&#xA;        fprintf(stderr, "Could not open video codec: %s\n", error);&#xA;    }&#xA;}&#xA;&#xA;&#xA;&#xA;void MovieCodec::write_video_frame( const cv::Mat&amp; image )&#xA;{&#xA;    int ret;&#xA;&#xA;    createFrame( image );&#xA;&#xA;&#xA;    if (m_formatCtx->oformat->flags &amp; 0x0020 )&#xA;    {&#xA;        /* Raw video case - directly store the picture in the packet */&#xA;        AVPacket pkt;&#xA;        av_init_packet(&amp;pkt);&#xA;&#xA;        pkt.flags |= AV_PKT_FLAG_KEY;&#xA;        pkt.stream_index = m_streamOut->index;&#xA;        pkt.data = m_frame->data[0];&#xA;        pkt.size = sizeof(AVPicture);&#xA;&#xA;//        ret = av_interleaved_write_frame(m_formatCtx, &amp;pkt);&#xA;        ret = av_write_frame( m_formatCtx, &amp;pkt );&#xA;    }&#xA;    else&#xA;    {&#xA;        AVPacket pkt;&#xA;        av_init_packet(&amp;pkt);&#xA;&#xA;        /* encode the image */&#xA;&#xA;//cv::Mat yuv420p( m_frame->height &#x2B; m_frame->height/2, m_frame->width, CV_8UC1, m_frame->data[0]);&#xA;//cv::Mat cvmIm;&#xA;//cv::cvtColor(yuv420p,cvmIm,CV_YUV420p2BGR);&#xA;//cv::imwrite("c:\\tmp\\YUVoriginal.png", cvmIm);&#xA;&#xA;        ret = avcodec_send_frame(m_codecCtx, m_frame);&#xA;&#xA;        if (ret &lt; 0)&#xA;        {&#xA;            char error[255];&#xA;            av_strerror(ret, error, 255);&#xA;            fprintf(stderr, "Error encoding video frame: %s\n", error);&#xA;            return;&#xA;        }&#xA;&#xA;        /* If size is zero, it means the image was buffered. */&#xA;//        ret = avcodec_receive_packet(m_codecCtx, &amp;pkt);&#xA;&#xA;        do&#xA;        {&#xA;            ret = avcodec_receive_packet(m_codecCtx, &amp;pkt);&#xA;&#xA;            if (ret == 0)&#xA;            {&#xA;                ret = av_write_frame( m_formatCtx, &amp;pkt );&#xA;                av_packet_unref(&amp;pkt);&#xA;&#xA;                break;&#xA;            }&#xA;//            else if ((ret &lt; 0) &amp;&amp; (ret != AVERROR(EAGAIN)))&#xA;//            {&#xA;//                return;&#xA;//            }&#xA;//            else if (ret == AVERROR(EAGAIN))&#xA;//            {&#xA;//                /* flush the encoder */&#xA;//                ret = avcodec_send_frame(m_codecCtx, NULL);&#xA;//&#xA;//                if (0 > ret)&#xA;//                    return;&#xA;//            }&#xA;        } while (ret == 0);&#xA;&#xA;        if( !ret &amp;&amp; pkt.size)&#xA;        {&#xA;            pkt.stream_index = m_streamOut->index;&#xA;&#xA;            /* Write the compressed frame to the media file. */&#xA;//            ret = av_interleaved_write_frame(m_formatCtx, &amp;pkt);&#xA;            ret = av_write_frame( m_formatCtx, &amp;pkt );&#xA;        }&#xA;        else&#xA;        {&#xA;            ret = 0;&#xA;        }&#xA;    }&#xA;&#xA;    if (ret != 0)&#xA;    {&#xA;        char error[255];&#xA;        av_strerror(ret, error, 255);&#xA;        fprintf(stderr, "Error while writing video frame: %s\n", error);&#xA;        return;&#xA;    }&#xA;&#xA;    s_frameCount&#x2B;&#x2B;;&#xA;}&#xA;

    &#xA;