[Libav-user] Trouble converting converting a series of SDL2's SDL_Surface->pixels to a video

jrmarsha jrmarsha at mtu.edu
Mon Apr 11 06:53:24 CEST 2016


Hello all,

I need help in understanding what I am doing wrong in a section of which 
takes a pixel array encoded as RGB24 from SDL2 and making it work with 
h.264 encoding.  I am converting to YUV format via sw_scale(), but still 
no luck.

Input: RGB24 encoded array as used in SDL2's SDL_Surface with dimension 
256 width by 144 height
Output: H.264 video with dimension 256 by 144


    void *encodeToVideo(void *ignore){

       AVCodec *codec;
       AVCodecContext *c= NULL;
       int i, ret, got_output;
       AVFrame *_frame;
       AVPacket pkt;
       uint8_t endcode[] = { 0, 0, 1, 0xb7 };
       i = 0;
       queue<SDL_Surface*> freeLater;

       /* find the video encoder */
       avcodec_register_all();
       codec = avcodec_find_encoder(AV_CODEC_ID_H264);
       if (!codec) {
         fprintf(stderr, "Codec not found\n");
         exit(1);
       }

       c = avcodec_alloc_context3(codec);
       if (!c) {
         fprintf(stderr, "Could not allocate video codec context\n");
         exit(1);
       }

       /* put sample parameters */
       c->bit_rate = 400000;
       c->width = 256;
       c->height = 144;
       /* frames per second */
       c->time_base = (AVRational){1,30};
       /* emit one intra frame every frames*/
       c->gop_size = 1;
       c->max_b_frames = 0;
       c->pix_fmt = AV_PIX_FMT_YUV420P;

       av_opt_set(c->priv_data, "zerolatency", "veryfast", 0);

       /* open codec */
       if (avcodec_open2(c, codec, NULL) < 0) {
         fprintf(stderr, "Could not open codec\n");
         exit(1);
       }

       _frame = av_frame_alloc();
       if (!_frame) {
           fprintf(stderr, "Could not allocate video frame\n");
           exit(1);
       }
       _frame->format = c->pix_fmt;
       _frame->width  = c->width;
       _frame->height = c->height;

       /* the image can be allocated by any means and av_image_alloc() is
       * just the most convenient way if av_malloc() is to be used */
       ret = av_image_alloc(_frame->data, _frame->linesize, c->width,
    c->height,
                              c->pix_fmt, 32);
       if (ret < 0) {
         fprintf(stderr, "Could not allocate raw picture buffer\n");
         exit(1);
       }

       while(!renderFramesDone || !renderFramesOut->empty()){
         if(renderFramesOut->empty()) continue;
         SDL_Surface *imageToEncode = renderFramesOut->front();
         renderFramesOut->pop();
         freeLater.push(imageToEncode);

         av_init_packet(&pkt);
         pkt.data = NULL;    // packet data will be allocated by the encoder
         pkt.size = 0;

         fflush(stdout);


         struct SwsContext* convertCtx;
         convertCtx = sws_getContext(256, 144, AV_PIX_FMT_RGB24,
                                     256, 144, AV_PIX_FMT_YUV420P, 0, 0,
    0, 0);

         uint8_t *inData[1] = {(uint8_t *)(imageToEncode->pixels)};
         int inLinesize[1] = { 256 };
         sws_scale(convertCtx, inData, inLinesize, 0, 144, _frame->data,
    _frame->linesize);
         sws_freeContext(convertCtx);

         _frame->pts = i++;

         /* encode the image */
         ret = avcodec_encode_video2(c, &pkt, _frame, &got_output);

         if (ret < 0) {
           fprintf(stdout, "Error encoding frame\n");
           exit(1);
         }

         if(got_output){
           fflush(stdout);
           fwrite(pkt.data, 1, pkt.size, stdout);
           av_packet_unref(&pkt);
         }

       }


       /* get the delayed frames */
       for (got_output = 1; got_output; i++) {
         fflush(stdout);

         ret = avcodec_encode_video2(c, &pkt, NULL, &got_output);
         if (ret < 0) {
           fprintf(stderr, "Error encoding frame\n");
           exit(1);
         }

         if (got_output) {
           fprintf(stderr, "Write frame %3d (size=%5d)\n", i, pkt.size);
           fwrite(pkt.data, 1, pkt.size, stdout);
           av_packet_unref(&pkt);
         }
       }


       /* add sequence end code to have a real mpeg file */
       fwrite(endcode, 1, sizeof(endcode), stdout);
       fclose(stdout);

       avcodec_close(c);
       av_free(c);
       av_freep(_frame->data);
       av_frame_free(&_frame);

       while(!freeLater.empty()){
         SDL_FreeSurface(freeLater.front());
         freeLater.pop();
       }

       encodeToVideoDone = true;
       return NULL;
    }


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20160411/870b29b5/attachment.html>


More information about the Libav-user mailing list