[Libav-user] Image conversion from and to a video file

Sethuraman V techmail.sethu at gmail.com
Thu May 14 06:36:25 CEST 2015


Hi All,

Following is the code snippet that I am reusing from remuxing.c, but when I
convert an image from YUV to RGB and again back to YUV, there are some
glitches added to the video stream on the frames that went for conversion,
rest of the frames are fine.

Please let me know what I am missing or how this can be achieved in a
different way without any glitches. FFmpeg version is 2.6.2


    //Allocation for RGB frame

    frame_rgb = av_frame_alloc();
    if (!frame_rgb) {
        goto end;
    }

    num_bytes = avpicture_get_size(PIX_FMT_RGB24, in_vcodec_ctx->width,
                      in_vcodec_ctx->height);

    buffer_rgb = (uint8_t *)av_malloc(num_bytes * sizeof(uint8_t));

    avpicture_fill((AVPicture *)frame_rgb, buffer_rgb, PIX_FMT_RGB24,
             in_vcodec_ctx->width, in_vcodec_ctx->height);


    //Allocation for YUV frame

    frame_yuv = av_frame_alloc();
    if (!frame_yuv) {
        goto end;
    }

    num_bytes = avpicture_get_size(in_vcodec_ctx->pix_fmt,
in_vcodec_ctx->width,
                      in_vcodec_ctx->height);

    buffer_yuv = (uint8_t *)av_malloc(num_bytes * sizeof(uint8_t));

    avpicture_fill((AVPicture *)frame_yuv, buffer_yuv,
in_vcodec_ctx->pix_fmt,
             in_vcodec_ctx->width, in_vcodec_ctx->height);


    //Allocation of SWS context

    sws_rgb_ctx = sws_getContext(in_vcodec_ctx->width,
in_vcodec_ctx->height,
                             in_vcodec_ctx->pix_fmt,
                             in_vcodec_ctx->width, in_vcodec_ctx->height,
                             PIX_FMT_RGB24,
                             SWS_BICUBIC, NULL, NULL, NULL);

    sws_yuv_ctx = sws_getContext(in_vcodec_ctx->width,
in_vcodec_ctx->height,
                             PIX_FMT_RGB24,
                             in_vcodec_ctx->width, in_vcodec_ctx->height,
                             in_vcodec_ctx->pix_fmt,
                             SWS_BICUBIC, NULL, NULL, NULL);

    for( ;; ) {

        ret = av_read_frame(ifmt_ctx, &pkt_in);
        if (ret < 0)
            break;

        in_stream  = ifmt_ctx->streams[pkt_in.stream_index];
        out_stream = ofmt_ctx->streams[pkt_in.stream_index];

        /* Process only video stream packets */
        if (pkt_in.stream_index == video_stream_idx) {

          /* Decode video frame */
          avcodec_decode_video2(in_vcodec_ctx, frame_yuv, &frame_finished,
&pkt_in);

          /* Process completed video frame and preferred type frame */
          if (frame_finished && AV_PICTURE_TYPE_I == frame_yuv->pict_type) {

              /* Convert the image from its native format to RGB */
              sws_scale
              (
                  sws_rgb_ctx,
                  (uint8_t const * const *)frame_yuv->data,
                  frame_yuv->linesize,
                  0,
                  in_vcodec_ctx->height,
                  frame_rgb->data,
                  frame_rgb->linesize
              );

              // perform necessary image modification

              /* Convert the image from RGB to input native format */
              sws_scale
              (
                  sws_yuv_ctx,
                  (uint8_t const * const *)frame_rgb->data,
                  frame_rgb->linesize,
                  0,
                  in_vcodec_ctx->height,
                  frame_yuv->data,
                  frame_yuv->linesize
              );

              av_init_packet(&pkt_yuv);

              /* packet data will be allocated by the encoder */
              pkt_yuv.data = NULL;

              /* encode the image */
              ret = avcodec_encode_video2(out_stream->codec, &pkt_yuv,
frame_yuv, &got_frame);
              if (ret < 0) {
                  fprintf(stderr, "Error encoding frame\n");
                  break;
              }

              if (got_frame) {

                  /* copy packet */
                  pkt_yuv.pts = av_rescale_q_rnd(pkt_in.pts,
in_stream->time_base, out_stream->time_base,
AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
                  pkt_yuv.dts = av_rescale_q_rnd(pkt_in.dts,
in_stream->time_base, out_stream->time_base,
AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
                  pkt_yuv.duration = av_rescale_q(pkt_in.duration,
in_stream->time_base, out_stream->time_base);
                  pkt_yuv.pos = -1;

                  ret = av_interleaved_write_frame(ofmt_ctx, &pkt_yuv);
                  if (ret < 0) {
                      fprintf(stderr, "Error muxing packet\n");
                      break;
                  }

                  av_free_packet(&pkt_yuv);
                  av_free_packet(&pkt_in);

                  continue;
              }
              else {
                  fprintf(stdout, "No output for encoded packet\n");

                  av_free_packet(&pkt_yuv);
              }
          }
        }

        /* copy packet */
        pkt_in.pts = av_rescale_q_rnd(pkt_in.pts, in_stream->time_base,
out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
        pkt_in.dts = av_rescale_q_rnd(pkt_in.dts, in_stream->time_base,
out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
        pkt_in.duration = av_rescale_q(pkt_in.duration,
in_stream->time_base, out_stream->time_base);
        pkt_in.pos = -1;

        ret = av_interleaved_write_frame(ofmt_ctx, &pkt_in);
        if (ret < 0) {
            fprintf(stderr, "Error muxing packet\n");
            break;
        }

        av_free_packet(&pkt_in);
    }

Regards,
Sethu

​P.S: Missed subject on earlier email.​
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20150514/85e38bd0/attachment.html>


More information about the Libav-user mailing list