[Libav-user] How to changes resolution to output file.

ABDALLAH Moussa Moussa.ABDALLAH at nexeya.com
Mon Mar 4 10:00:11 EET 2019


Hi !

This is the code I used to decode, change the resolution and encode the frame, but when I ru nit it send me the message : [mjpeg @ 0x3c15240] This encoder requires using the avcodec_send_frame() API.
And When I use avcodec_send_frame() with avcodec_receuve_packet() It’s doesn’t work.

        av_init_packet( &pkt );
        int ii=0;
        while (ii<258)
        {
            if (av_read_frame (ifcx, & pkt) >= 0)
            {
                // Make sure we start on a key video frame
                if (got_key_frame == 0)
                {
                    if (pkt.stream_index == i_vindex)
                    {
                        if (pkt.flags & AV_PKT_FLAG_KEY)
                        {
                            got_key_frame = 1;
                        }
                        else
                            continue ; // Not key frame
                    }
                }

                // Manage pkt

                // pts can be AV_NOPTS_VALUE = 0x8000... at start
                if (pkt.pts == AV_NOPTS_VALUE)
                    pkt.pts = pkt.dts = 0 ;

                if ( pkt.stream_index == i_vindex )
                {
                    printf("8\n");
                    // pkt is video
                    avcodec_decode_video2(cctx, pFrame, &frameFinished, &pkt);
                    if (frameFinished){
                        printf("video_frame n:%d    coded_n:%d\n" , video_frame_count++);
                    }
                    static struct SwsContext *img_convert_ctx_in = NULL;
                    if (img_convert_ctx_in == NULL)
                    {
                        img_convert_ctx_in =sws_getContext( cctx->width,
                            cctx->height,
                            AV_PIX_FMT_YUV420P,
                            changeWidth,
                            changeHeight,
                            AV_PIX_FMT_YUV420P,
                            SWS_BICUBIC,
                            NULL,
                            NULL,
                            NULL );

                    }
                    //scale the frames
                    sws_scale(img_convert_ctx_in,
                        pFrame->data,
                        pFrame->linesize,
                        0,
                        cctx->height,
                        outFrame->data,
                        outFrame->linesize);
                    printf("9\n");
                    //initiate the pts value
                    if ( frameNo == 0)
                        outFrame->pts = 0;

                    //calculate the pts value & set it.
                    outFrame->pts += av_rescale_q(1, ovst->codec->time_base, ovst->time_base);
                    //encode frames into packages. Package passed in @pkt.
                    if(avcodec_encode_video2(cctx, &pkt, outFrame, &pp) < 0 )
                    printf("Encoding frames into packages, failed.\n ");

                    frameNo++;
                    printf("10\n");
                    //write the packages into file, resulting in creating a video file.
                    av_interleaved_write_frame(ofcx,&pkt);
                }
                av_free_packet( &pkt );
                av_init_packet( &pkt );
            }
            ii++;
        }


De : Libav-user <libav-user-bounces at ffmpeg.org> De la part de ABDALLAH Moussa
Envoyé : dimanche 3 mars 2019 13:05
À : This list is about using libavcodec, libavformat, libavutil, libavdevice and libavfilter. <libav-user at ffmpeg.org>
Objet : Re: [Libav-user] How to changes resolution to output file.

Hi!

Thanks you for your answer. When I tried to do this, I had an error in the enconding step. I got on the console a message whixh tell me that I can’t use the function avcodec_encode_video2() but I have to use avcodec_send_frame() and avcodec_receive_packet().

Le 3 mars 2019 à 06:30, Yurii Monakov <monakov.y at gmail.com<mailto:monakov.y at gmail.com>> a écrit :
Hi!

You should decode input packets from camera to AVFrames using decoding API. After that it will be possible to change video frame resolution and encode scaled frames into video file with encoding API.


чт, 28 февр. 2019 г. в 18:39, ABDALLAH Moussa <Moussa.ABDALLAH at nexeya.com<mailto:Moussa.ABDALLAH at nexeya.com>>:
After many try to change resolution of my output video file, I failed.. I didn’t understand how to use the function sws_scale() with AVPacket where is my stream video.
Could you help me please ?

This is my source code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <sstream>

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libswscale/swscale.h>
}

int main(int argc, char** argv) {

    // Open the initial context variables that are needed
    AVFormatContext* ifcx = NULL;
    AVCodecContext* cctx = NULL;
    AVStream        * ivst = NULL;
    int     i_vindex;
    int     got_key_frame = 0;

    AVFormatContext * ofcx;
    AVOutputFormat  * ofmt;
    AVStream        * ovst = NULL, * oast = NULL;

    AVPacket        pkt;
    int         ix;
    struct SwsContext *resize;

    // pts computing
    AVRational      vPtsFactor, aPtsFactor = { 0, 0 } ;

    // Register everything
   // av_register_all();
   // avformat_network_init();
    printf("1\n");
    //open http
    if (avformat_open_input(&ifcx, "http://192.9.200.121/ipcam/mjpeg.cgi",
            NULL, NULL) != 0) {
        return EXIT_FAILURE;
    }

    if (avformat_find_stream_info(ifcx, NULL) < 0) {
        return EXIT_FAILURE;
    }
    printf("2\n");
    //search video stream
    i_vindex = -1;
    for (ix = 0; ix < (int) ifcx->nb_streams; ix++) {
        // Get the codec
        cctx = ifcx->streams[ ix ]->codec;
        if (cctx->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            ivst = ifcx->streams[ ix ];
            i_vindex = ix;
            continue ;
        }
    }
        if ( i_vindex < 0 )
        {
            printf( "KNC230ERROR: Cannot find input video stream\n" );
            avformat_close_input( &ifcx );
        }
    printf("3\n");

       //open output file -------------------------------------------
        ofmt = av_guess_format( NULL, "/home/Nexeya/capture6.mkv", NULL );
        ofcx = avformat_alloc_context();
        ofcx->oformat = ofmt;
        avio_open2( &ofcx->pb, "/home/Nexeya/capture6.mkv", AVIO_FLAG_WRITE, NULL, NULL );
printf("4\n");
        // Create video output stream -------------------------------------------
        //ovst = avformat_new_stream( ofcx, (AVCodec *) cctx->codec );
        ovst = avformat_new_stream( ofcx, NULL );
        avcodec_copy_context( ovst->codec, cctx);

        ovst->sample_aspect_ratio.num = cctx->sample_aspect_ratio.num;
        ovst->sample_aspect_ratio.den = cctx->sample_aspect_ratio.den;
printf("5\n");
        // Assume r_frame_rate is accurate
        ivst->r_frame_rate.num=25;
        ivst->r_frame_rate.den=1;
        ovst->r_frame_rate      = ivst->r_frame_rate;
        ovst->avg_frame_rate    = ovst->r_frame_rate;
printf("6\n");
        // Initialize many things ...
        avformat_write_header( ofcx, NULL );

        snprintf( ofcx->filename, sizeof( ofcx->filename ), "%s", "/home/Nexeya/capture6.mkv" );

        // Video pts conversion factor
        // The input and output time_base may be different
        vPtsFactor.num = ivst->time_base.num * ovst->time_base.den ;
        vPtsFactor.den = ivst->time_base.den * ovst->time_base.num ;
        ix = (uint32_t) av_gcd (vPtsFactor.num, vPtsFactor.den) ;
        vPtsFactor.num /= ix ;
        vPtsFactor.den /= ix ;
printf("7\n");

        resize = sws_getContext(cctx->width, cctx->height, AV_PIX_FMT_YUV420P, 320, 240, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
        //start reading pkts from stream and write them to file
        printf("Start record\n");
        av_init_packet( &pkt );
        int ii=0;
        while (ii<258)
        {
            if (av_read_frame (ifcx, & pkt) >= 0)
            {
                // Make sure we start on a key video frame
                if (got_key_frame == 0)
                {
                    if (pkt.stream_index == i_vindex)
                    {
                        if (pkt.flags & AV_PKT_FLAG_KEY)
                        {
                            got_key_frame = 1;
                        }
                        else
                            continue ; // Not key frame
                    }
                }

                // Manage pkt

                // pts can be AV_NOPTS_VALUE = 0x8000... at start
                if (pkt.pts == AV_NOPTS_VALUE)
                    pkt.pts = pkt.dts = 0 ;

                if ( pkt.stream_index == i_vindex )
                {
                    // pkt is video

                    pkt.stream_index = ovst->id;

                    // Compute pts
                    pkt.pts = pkt.dts = (pkt.pts * vPtsFactor.num) / vPtsFactor.den ;
                    sws_scale(resize, pkt.data, pkt.linesize, 0, cctx->height, pkt.data, pkt.linesize);
                    av_write_frame( ofcx, &pkt );
                }

                av_free_packet( &pkt );
                av_init_packet( &pkt );
            }
            ii++;
        }
        printf("End record\n");
        // Stop command received
        av_read_pause           ( ifcx );
        av_write_trailer        ( ofcx );
        avio_close              ( ofcx->pb );
        avformat_close_input    ( & ifcx );
        avformat_free_context   ( ofcx );
    return (EXIT_SUCCESS);
}

Thanks you very much for your help.

De : Libav-user <libav-user-bounces at ffmpeg.org<mailto:libav-user-bounces at ffmpeg.org>> De la part de Michael Armes
Envoyé : mercredi 27 février 2019 22:27
À : This list is about using libavcodec, libavformat, libavutil, libavdevice and libavfilter. <libav-user at ffmpeg.org<mailto:libav-user at ffmpeg.org>>
Objet : Re: [Libav-user] How to changes resolution to output file.

I did not find that setting bitrate had any effect in my scenarios with mp4/mov. I had to manually control my color depth and resolution (and set framerate) to hit my desired bitrate. I never did have to convert pixel formats, but my read of the docs is that sws_scale can do this as long as you set your SwsContext appropriately.

On Wed, Feb 27, 2019 at 11:08 AM ABDALLAH Moussa <Moussa.ABDALLAH at nexeya.com<mailto:Moussa.ABDALLAH at nexeya.com>> wrote:
Thanks you for your help!
To change the bit_rate I have to use sw_scale too?

Le 27 févr. 2019 à 18:49, Michael Armes <michael.armes at gmail.com<mailto:michael.armes at gmail.com>> a écrit :
You need to scale *each frame* with sws_scale from lib_av (https://libav.org/documentation/doxygen/master/group__libsws.html#gae531c9754c9205d90ad6800015046d74). I suggest you look at the example code linked in the documentation for reference.

On Wed, Feb 27, 2019 at 9:38 AM ABDALLAH Moussa <Moussa.ABDALLAH at nexeya.com<mailto:Moussa.ABDALLAH at nexeya.com>> wrote:
Hello,

I am trying to record a stream video to a output file mkv. I set my camera with the resolution 1280x720 and I would like to change it with ffmpeg on my program how can I do that please ?

I have success to change the framerate but I failed  with the resolution or other option like bit_rate :

        ivst->r_frame_rate.num=25;
        ivst->r_frame_rate.den=1;
        ovst->r_frame_rate      = ivst->r_frame_rate;
        ovst->avg_frame_rate    = ovst->r_frame_rate;
        ivst->codec->bit_rate = 3000000;
        ovst->codec->bit_rate = 3000000;
        ivst->codec->height = 320;
        ivst->codec->width = 240;
        ovst->codec->height = 320;
        ovst->codec->width = 240;

Thanks you for your help !
_______________________________________________
Libav-user mailing list
Libav-user at ffmpeg.org<mailto:Libav-user at ffmpeg.org>
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
libav-user-request at ffmpeg.org<mailto:libav-user-request at ffmpeg.org> with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
Libav-user at ffmpeg.org<mailto:Libav-user at ffmpeg.org>
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
libav-user-request at ffmpeg.org<mailto:libav-user-request at ffmpeg.org> with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
Libav-user at ffmpeg.org<mailto:Libav-user at ffmpeg.org>
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
libav-user-request at ffmpeg.org<mailto:libav-user-request at ffmpeg.org> with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
Libav-user at ffmpeg.org<mailto:Libav-user at ffmpeg.org>
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
libav-user-request at ffmpeg.org<mailto:libav-user-request at ffmpeg.org> with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
Libav-user at ffmpeg.org<mailto:Libav-user at ffmpeg.org>
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
libav-user-request at ffmpeg.org<mailto:libav-user-request at ffmpeg.org> with subject "unsubscribe".
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20190304/2e96ec92/attachment.html>


More information about the Libav-user mailing list