Oh yes. I also tried it with values in the range 1 & 31 and no
difference.

Clive

-----Original Message-----
From: [email protected]
[mailto:[email protected]] On Behalf Of Clive Taylor
Sent: 02 April 2009 14:46
To: Libav* user questions and discussions
Subject: Re: [libav-user] Writing single frames to JPEG

Stas,

It's beginning to look as though setting the quality in the codec
context sets it for the duration of the codec instance's lifetime. OK
that sentence isn't very clear, but what I've tried to do is to read one
particular frame and then to write it out at different quality settings.
What I did was something like this:

        //
        //      Allocate the output codec context
        //
        pOCodecCtx = avcodec_alloc_context ( );
        if ( !pOCodecCtx ) {
                printf ( "Unable to allocate output codec context.\n" );
                av_free ( pFrameRGB );
                av_free ( pFrame );
                avcodec_close ( pCodecCtx );
                av_close_input_file ( pFormatCtx );
                exit ( 2 );
                }
        //
        //      Initialise format parameters
        //
        pOCodecCtx->bit_rate      = pCodecCtx->bit_rate;
        pOCodecCtx->width         = pCodecCtx->width;
        pOCodecCtx->height        = pCodecCtx->height;
        pOCodecCtx->pix_fmt       = ImgFmt;
        pOCodecCtx->codec_id      = CODEC_ID_MJPEG;
        pOCodecCtx->codec_type    = CODEC_TYPE_VIDEO;
        pOCodecCtx->time_base.num = pCodecCtx->time_base.num;
        pOCodecCtx->time_base.den = pCodecCtx->time_base.den;
        //
        //      Allocate the JPEG encoder
        //
        pOCodec = avcodec_find_encoder ( pOCodecCtx->codec_id );
        if ( !pOCodec ) {
                printf ( "Unable to find JPEG encoder.\n" );
                av_free ( pFrameRGB );
                av_free ( pFrame );
                avcodec_close ( pCodecCtx );
                av_close_input_file ( pFormatCtx );
                exit ( 2 );
                }
        //
        //      Open the JPEG encoder
        //
        if ( avcodec_open ( pOCodecCtx, pOCodec ) < 0 ) {
                printf ( "Unable to open JPEG encoder.\n" );
                av_free ( pFrameRGB );
                av_free ( pFrame );
                avcodec_close ( pCodecCtx );
                av_close_input_file ( pFormatCtx );
                exit ( 2 );
                }

That gets me the JPEG encoder. Inside a "while ( 1 )" loop, I then do
this

                if ( !GetNextFrame ( pFormatCtx, pCodecCtx, VideoStream,
pFrame, i ) )
                        break;
#ifdef  DOJPEG
                if ( (UFrameInt == -1) && (i == 8000) ) {
                        for ( QNo = 1; QNo < 100; QNo++ ) {
                                //
                                //      Encode the frame as a JPEG image

                                //
                                pFrame->pts = i + QNo;
                                pOCodecCtx->qmin = pOCodecCtx->qmax = 
                                                        (100 - QNo) *
FF_LAMBDA_MAX / 100;
                                pOCodecCtx->mb_lmin = pOCodecCtx->lmin =

                                                        pOCodecCtx->qmin
* FF_QP2LAMBDA;
                                pOCodecCtx->mb_lmax = pOCodecCtx->lmax =

                                                        pOCodecCtx->qmax
* FF_QP2LAMBDA;
                                pOCodecCtx->flags   = CODEC_FLAG_QSCALE;
                                pFrame->quality =
pOCodecCtx->global_quality =
pOCodecCtx->qmin * FF_QP2LAMBDA;
                                BufSizActual = avcodec_encode_video (
pOCodecCtx,
Buffer,
        
BufSiz,
        
pFrame );
                                //
                                //      Write JPEG to file
                                //
                                sprintf ( JPEGFName, "f%06dq%02d.jpg",
i, QNo );
                                JPEGFile = fopen ( JPEGFName, "wb" );
                                fwrite ( Buffer, 1, BufSizActual,
JPEGFile );
                                fclose ( JPEGFile );
                                }
                        }
                else
#endif  // def DOJPEG
                //
                //      Do something else
                //

In this code, i is the frame counter, UFrameInt is just a value set on
the command line (in this case to -1) and GetNextFrame ( ) is a wrapper
around av_read_frame ( ). It was a lot tidier before I put it into this
e-mail, too.

So, what I'm trying to do is to set all quality values from 1% to 99%
and write them out to files whose name reflects the frame number and the
quality (f008000q01.jpg - f008000q99.jpg). 

I'm using an IDE (don't tell anyone, but it's Microsoft Visual Studio 6)
so I can watch the qmin and qmax values as they change, and I can see
the size of the output buffer for each setting of the quality and other
VBR values. In the case of the video file that I'm using here, I always
get a buffer size of 11556 bytes, no matter what the global_quality,
qmin, qmax, lmin, lmax, mb_lmin and mb_lmax elements of the codec
context are set to.

>From this, I'd guess that there's something else that needs to be
changed or set somewhere, or that the encoder has to be closed and
reopened for each quality value change and the data is not treated as
dynamic.

It's almost tempting to tell the customer that they need to use a
hardware JPEG encoder, 'cause it'd be a damned sight cheaper than having
to pay me to do all of these experiments, but a) I did quite  lot of
work with early CCube encoders (late 1980s, early 1990s) and they
weren't much fun either, and b) I need the money.

Clive


-----Original Message-----
From: [email protected]
[mailto:[email protected]] On Behalf Of Stas Oskin
Sent: 02 April 2009 12:46
To: Libav* user questions and discussions
Subject: Re: [libav-user] Writing single frames to JPEG

>
> Oh and the following comment in AVCodec.h
>
> /**\
>  * quality (between 1 (good) and FF_LAMBDA_MAX (bad)) \
>  * - encoding: set by libavcodec. For coded_picture (and set by user
for
> input).\
>
> And so on. It's round about line 607 in avcodec.h
>
> Clive
>


Anyone? :)
_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user


_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user


_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user

Reply via email to