diff mbox

[FFmpeg-devel,V2] doc/examples: Add a qsv encoder example

Message ID 1501694829-13716-1-git-send-email-zhong.li@intel.com
State New
Headers show

Commit Message

Zhong Li Aug. 2, 2017, 5:27 p.m. UTC
It is an evolution from the exmaple "encode_video.c" to support qsv encoder.

V1->V2: Split to a separated qsv encoding example, instead of a patch
based on encode_video.c

Signed-off-by: Zhong Li <zhong.li@intel.com>
---
 configure             |   2 +
 doc/Makefile          |   1 +
 doc/examples/qsvenc.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 214 insertions(+)
 create mode 100644 doc/examples/qsvenc.c

Comments

Steven Liu Aug. 2, 2017, 6:01 a.m. UTC | #1
2017-08-03 1:27 GMT+08:00 Zhong Li <zhong.li@intel.com>:
> It is an evolution from the exmaple "encode_video.c" to support qsv encoder.
>
> V1->V2: Split to a separated qsv encoding example, instead of a patch
> based on encode_video.c
>
> Signed-off-by: Zhong Li <zhong.li@intel.com>
> ---
>  configure             |   2 +
>  doc/Makefile          |   1 +
>  doc/examples/qsvenc.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 214 insertions(+)
>  create mode 100644 doc/examples/qsvenc.c
>
> diff --git a/configure b/configure
> index 66c7b94..676cd85 100755
> --- a/configure
> +++ b/configure
> @@ -1472,6 +1472,7 @@ EXAMPLE_LIST="
>      metadata_example
>      muxing_example
>      qsvdec_example
> +    qsvenc_example
>      remuxing_example
>      resampling_audio_example
>      scaling_video_example
> @@ -3213,6 +3214,7 @@ hw_decode_example_deps="avcodec avformat avutil"
>  metadata_example_deps="avformat avutil"
>  muxing_example_deps="avcodec avformat avutil swscale"
>  qsvdec_example_deps="avcodec avutil libmfx h264_qsv_decoder"
> +qsvenc_example_deps="avcodec avutil libmfx"
>  remuxing_example_deps="avcodec avformat avutil"
>  resampling_audio_example_deps="avutil swresample"
>  scaling_video_example_deps="avutil swscale"
> diff --git a/doc/Makefile b/doc/Makefile
> index b670f0b..ed41763 100644
> --- a/doc/Makefile
> +++ b/doc/Makefile
> @@ -52,6 +52,7 @@ DOC_EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE)         += hw_decode
>  DOC_EXAMPLES-$(CONFIG_METADATA_EXAMPLE)          += metadata
>  DOC_EXAMPLES-$(CONFIG_MUXING_EXAMPLE)            += muxing
>  DOC_EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE)            += qsvdec
> +DOC_EXAMPLES-$(CONFIG_QSVENC_EXAMPLE)            += qsvenc
>  DOC_EXAMPLES-$(CONFIG_REMUXING_EXAMPLE)          += remuxing
>  DOC_EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE)  += resampling_audio
>  DOC_EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE)     += scaling_video
> diff --git a/doc/examples/qsvenc.c b/doc/examples/qsvenc.c
> new file mode 100644
> index 0000000..3b94cc8
> --- /dev/null
> +++ b/doc/examples/qsvenc.c
> @@ -0,0 +1,211 @@
> +/*
> + * Copyright (c) 2017 Fabrice Bellard, Zhong Li
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +/**
> + * @file
> + * Intel QSV-accelerated encoding example
> + *
> + * @example qsvenc.c
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#include <libavcodec/avcodec.h>
> +
> +#include <libavutil/opt.h>
> +#include <libavutil/imgutils.h>
> +#include "libavutil/buffer.h"
> +#include "libavutil/hwcontext.h"
> +
> +static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,
> +                   FILE *outfile)
> +{
> +    int ret;
> +
> +    /* send the frame to the encoder */
> +    if (frame)
> +        printf("Send frame %3"PRId64"\n", frame->pts);
> +
> +    ret = avcodec_send_frame(enc_ctx, frame);
> +    if (ret < 0) {
> +        fprintf(stderr, "Error sending a frame for encoding\n");
> +        exit(1);
> +    }
> +
> +    while (ret >= 0) {
> +        ret = avcodec_receive_packet(enc_ctx, pkt);
> +        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
> +            return;
> +        else if (ret < 0) {
> +            fprintf(stderr, "Error during encoding\n");
> +            exit(1);
> +        }
> +
> +        printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);
> +        fwrite(pkt->data, 1, pkt->size, outfile);
> +        av_packet_unref(pkt);
> +    }
> +}
> +
> +int main(int argc, char **argv)
> +{
> +    const char *filename, *codec_name;
> +    const AVCodec *codec;
> +    AVCodecContext *c= NULL;
Why don't use AVCodecParameters?
> +    int i, ret, x, y;
> +    FILE *f;
> +    AVFrame *frame;
> +    AVPacket *pkt;
> +    AVBufferRef *encode_device = NULL;
> +
> +    if (argc <= 2) {
> +        fprintf(stderr, "Usage: %s <output file> <codec name>\n", argv[0]);
> +        exit(0);
> +    }
> +    filename = argv[1];
> +    codec_name = argv[2];
> +
> +    if (!strstr(codec_name, "qsv")) {
> +        fprintf(stderr, "no qsv codec found\n");
> +        exit(0);
> +    }
> +
> +    avcodec_register_all();
> +
> +    /* open the qsv hardware device */
> +    ret = av_hwdevice_ctx_create(&encode_device, AV_HWDEVICE_TYPE_QSV,
> +                                 NULL, NULL, 0);
> +    if (ret < 0) {
> +        fprintf(stderr, "Cannot open the hardware device\n");
> +        exit(1);
> +    }
> +
> +    /* find the encoder */
> +    codec = avcodec_find_encoder_by_name(codec_name);
> +    if (!codec) {
> +        fprintf(stderr, "Codec '%s' not found\n", codec_name);
> +        exit(1);
> +    }
> +
> +    c = avcodec_alloc_context3(codec);
> +    if (!c) {
> +        fprintf(stderr, "Could not allocate video codec context\n");
> +        exit(1);
> +    }
> +
> +    pkt = av_packet_alloc();
> +    if (!pkt)
> +        exit(1);
> +
> +    /* put sample parameters */
> +    c->bit_rate = 400000;
> +    /* resolution must be a multiple of two */
> +    c->width = 352;
> +    c->height = 288;
> +    /* frames per second */
> +    c->time_base = (AVRational){1, 25};
> +    c->framerate = (AVRational){25, 1};
> +
> +    /* emit one intra frame every ten frames
> +     * check frame pict_type before passing frame
> +     * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
> +     * then gop_size is ignored and the output of encoder
> +     * will always be I frame irrespective to gop_size
> +     */
> +    c->gop_size = 10;
> +    c->max_b_frames = 1;
> +    c->pix_fmt = AV_PIX_FMT_NV12;
> +    c->hw_device_ctx = av_buffer_ref(encode_device);
> +
> +    /* open it */
> +    ret = avcodec_open2(c, codec, NULL);
> +    if (ret < 0) {
> +        fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
> +        exit(1);
> +    }
> +
> +    f = fopen(filename, "wb");
> +    if (!f) {
> +        fprintf(stderr, "Could not open %s\n", filename);
> +        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;
> +
> +    ret = av_frame_get_buffer(frame, 32);
> +    if (ret < 0) {
> +        fprintf(stderr, "Could not allocate the video frame data\n");
> +        exit(1);
> +    }
> +
> +    /* encode 1 second of video */
> +    for (i = 0; i < 25; i++) {
> +        fflush(stdout);
> +
> +        /* make sure the frame data is writable */
> +        ret = av_frame_make_writable(frame);
> +        if (ret < 0)
> +            exit(1);
> +
> +        /* prepare a dummy image */
> +        /* Y */
> +        for (y = 0; y < c->height; y++) {
> +            for (x = 0; x < c->width; x++) {
> +                frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
> +            }
> +        }
> +
> +        /* Cb and Cr */
> +        for (y = 0; y < c->height/2; y++) {
> +            for (x = 0; x < c->width/2; x++) {
> +                frame->data[1][y * frame->linesize[1] + 2 * x] = 128 + y + i * 2;
> +                frame->data[1][y * frame->linesize[1] + 2 * x + 1] = 64 + x + i * 5;
> +            }
> +        }
> +
> +        frame->pts = i;
> +
> +        /* encode the image */
> +        encode(c, frame, pkt, f);
> +    }
> +
> +    /* flush the encoder */
> +    encode(c, NULL, pkt, f);
> +
> +    fclose(f);
> +
> +    avcodec_free_context(&c);
> +    av_frame_free(&frame);
> +    av_packet_free(&pkt);
> +    av_buffer_unref(&encode_device);
> +
> +    return 0;
> +}
> --
> 1.8.3.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Zhong Li Aug. 7, 2017, 2:45 a.m. UTC | #2
> -----Original Message-----

> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf

> Of Steven Liu

> Sent: Wednesday, August 2, 2017 2:01 PM

> To: FFmpeg development discussions and patches

> <ffmpeg-devel@ffmpeg.org>

> Subject: Re: [FFmpeg-devel] [PATCH V2] doc/examples: Add a qsv encoder

> example

> 

> 2017-08-03 1:27 GMT+08:00 Zhong Li <zhong.li@intel.com>:

> > It is an evolution from the exmaple "encode_video.c" to support qsv

> encoder.

> >

> > V1->V2: Split to a separated qsv encoding example, instead of a patch

> > based on encode_video.c

> >

> > Signed-off-by: Zhong Li <zhong.li@intel.com>

> > ---

> >  configure             |   2 +

> >  doc/Makefile          |   1 +

> >  doc/examples/qsvenc.c | 211

> > ++++++++++++++++++++++++++++++++++++++++++++++++++

> >  3 files changed, 214 insertions(+)

> >  create mode 100644 doc/examples/qsvenc.c

> >

> > diff --git a/configure b/configure

> > index 66c7b94..676cd85 100755

> > --- a/configure

> > +++ b/configure

> > @@ -1472,6 +1472,7 @@ EXAMPLE_LIST="

> >      metadata_example

> >      muxing_example

> >      qsvdec_example

> > +    qsvenc_example

> >      remuxing_example

> >      resampling_audio_example

> >      scaling_video_example

> > @@ -3213,6 +3214,7 @@ hw_decode_example_deps="avcodec avformat

> avutil"

> >  metadata_example_deps="avformat avutil"

> >  muxing_example_deps="avcodec avformat avutil swscale"

> >  qsvdec_example_deps="avcodec avutil libmfx h264_qsv_decoder"

> > +qsvenc_example_deps="avcodec avutil libmfx"

> >  remuxing_example_deps="avcodec avformat avutil"

> >  resampling_audio_example_deps="avutil swresample"

> >  scaling_video_example_deps="avutil swscale"

> > diff --git a/doc/Makefile b/doc/Makefile index b670f0b..ed41763 100644

> > --- a/doc/Makefile

> > +++ b/doc/Makefile

> > @@ -52,6 +52,7 @@ DOC_EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE)

> += hw_decode

> >  DOC_EXAMPLES-$(CONFIG_METADATA_EXAMPLE)          +=

> metadata

> >  DOC_EXAMPLES-$(CONFIG_MUXING_EXAMPLE)            +=

> muxing

> >  DOC_EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE)            += qsvdec

> > +DOC_EXAMPLES-$(CONFIG_QSVENC_EXAMPLE)            += qsvenc

> >  DOC_EXAMPLES-$(CONFIG_REMUXING_EXAMPLE)          +=

> remuxing

> >  DOC_EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE)  +=

> resampling_audio

> >  DOC_EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE)     +=

> scaling_video

> > diff --git a/doc/examples/qsvenc.c b/doc/examples/qsvenc.c new file

> > mode 100644 index 0000000..3b94cc8

> > --- /dev/null

> > +++ b/doc/examples/qsvenc.c

> > @@ -0,0 +1,211 @@

> > +/*

> > + * Copyright (c) 2017 Fabrice Bellard, Zhong Li

> > + *

> > + * Permission is hereby granted, free of charge, to any person

> > +obtaining a copy

> > + * of this software and associated documentation files (the

> > +"Software"), to deal

> > + * in the Software without restriction, including without limitation

> > +the rights

> > + * to use, copy, modify, merge, publish, distribute, sublicense,

> > +and/or sell

> > + * copies of the Software, and to permit persons to whom the Software

> > +is

> > + * furnished to do so, subject to the following conditions:

> > + *

> > + * The above copyright notice and this permission notice shall be

> > +included in

> > + * all copies or substantial portions of the Software.

> > + *

> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY

> KIND,

> > +EXPRESS OR

> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF

> > +MERCHANTABILITY,

> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO

> EVENT

> > +SHALL

> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,

> DAMAGES

> > +OR OTHER

> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR

> OTHERWISE,

> > +ARISING FROM,

> > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR

> OTHER

> > +DEALINGS IN

> > + * THE SOFTWARE.

> > + */

> > +

> > +/**

> > + * @file

> > + * Intel QSV-accelerated encoding example

> > + *

> > + * @example qsvenc.c

> > + */

> > +

> > +#include <stdio.h>

> > +#include <stdlib.h>

> > +#include <string.h>

> > +

> > +#include <libavcodec/avcodec.h>

> > +

> > +#include <libavutil/opt.h>

> > +#include <libavutil/imgutils.h>

> > +#include "libavutil/buffer.h"

> > +#include "libavutil/hwcontext.h"

> > +

> > +static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket

> *pkt,

> > +                   FILE *outfile)

> > +{

> > +    int ret;

> > +

> > +    /* send the frame to the encoder */

> > +    if (frame)

> > +        printf("Send frame %3"PRId64"\n", frame->pts);

> > +

> > +    ret = avcodec_send_frame(enc_ctx, frame);

> > +    if (ret < 0) {

> > +        fprintf(stderr, "Error sending a frame for encoding\n");

> > +        exit(1);

> > +    }

> > +

> > +    while (ret >= 0) {

> > +        ret = avcodec_receive_packet(enc_ctx, pkt);

> > +        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)

> > +            return;

> > +        else if (ret < 0) {

> > +            fprintf(stderr, "Error during encoding\n");

> > +            exit(1);

> > +        }

> > +

> > +        printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts,

> pkt->size);

> > +        fwrite(pkt->data, 1, pkt->size, outfile);

> > +        av_packet_unref(pkt);

> > +    }

> > +}

> > +

> > +int main(int argc, char **argv)

> > +{

> > +    const char *filename, *codec_name;

> > +    const AVCodec *codec;

> > +    AVCodecContext *c= NULL;

> Why don't use AVCodecParameters?


Could you give more detail about the reason? 
AVCodecParameters is used for encoded bitstream. Here just encoding a raw yuv, seems AVCodecContext is enough.

> > +    int i, ret, x, y;

> > +    FILE *f;

> > +    AVFrame *frame;

> > +    AVPacket *pkt;

> > +    AVBufferRef *encode_device = NULL;

> > +

> > +    if (argc <= 2) {

> > +        fprintf(stderr, "Usage: %s <output file> <codec name>\n",

> argv[0]);

> > +        exit(0);

> > +    }

> > +    filename = argv[1];

> > +    codec_name = argv[2];

> > +

> > +    if (!strstr(codec_name, "qsv")) {

> > +        fprintf(stderr, "no qsv codec found\n");

> > +        exit(0);

> > +    }

> > +

> > +    avcodec_register_all();

> > +

> > +    /* open the qsv hardware device */

> > +    ret = av_hwdevice_ctx_create(&encode_device,

> AV_HWDEVICE_TYPE_QSV,

> > +                                 NULL, NULL, 0);

> > +    if (ret < 0) {

> > +        fprintf(stderr, "Cannot open the hardware device\n");

> > +        exit(1);

> > +    }

> > +

> > +    /* find the encoder */

> > +    codec = avcodec_find_encoder_by_name(codec_name);

> > +    if (!codec) {

> > +        fprintf(stderr, "Codec '%s' not found\n", codec_name);

> > +        exit(1);

> > +    }

> > +

> > +    c = avcodec_alloc_context3(codec);

> > +    if (!c) {

> > +        fprintf(stderr, "Could not allocate video codec context\n");

> > +        exit(1);

> > +    }

> > +

> > +    pkt = av_packet_alloc();

> > +    if (!pkt)

> > +        exit(1);

> > +

> > +    /* put sample parameters */

> > +    c->bit_rate = 400000;

> > +    /* resolution must be a multiple of two */

> > +    c->width = 352;

> > +    c->height = 288;

> > +    /* frames per second */

> > +    c->time_base = (AVRational){1, 25};

> > +    c->framerate = (AVRational){25, 1};

> > +

> > +    /* emit one intra frame every ten frames

> > +     * check frame pict_type before passing frame

> > +     * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I

> > +     * then gop_size is ignored and the output of encoder

> > +     * will always be I frame irrespective to gop_size

> > +     */

> > +    c->gop_size = 10;

> > +    c->max_b_frames = 1;

> > +    c->pix_fmt = AV_PIX_FMT_NV12;

> > +    c->hw_device_ctx = av_buffer_ref(encode_device);

> > +

> > +    /* open it */

> > +    ret = avcodec_open2(c, codec, NULL);

> > +    if (ret < 0) {

> > +        fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));

> > +        exit(1);

> > +    }

> > +

> > +    f = fopen(filename, "wb");

> > +    if (!f) {

> > +        fprintf(stderr, "Could not open %s\n", filename);

> > +        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;

> > +

> > +    ret = av_frame_get_buffer(frame, 32);

> > +    if (ret < 0) {

> > +        fprintf(stderr, "Could not allocate the video frame data\n");

> > +        exit(1);

> > +    }

> > +

> > +    /* encode 1 second of video */

> > +    for (i = 0; i < 25; i++) {

> > +        fflush(stdout);

> > +

> > +        /* make sure the frame data is writable */

> > +        ret = av_frame_make_writable(frame);

> > +        if (ret < 0)

> > +            exit(1);

> > +

> > +        /* prepare a dummy image */

> > +        /* Y */

> > +        for (y = 0; y < c->height; y++) {

> > +            for (x = 0; x < c->width; x++) {

> > +                frame->data[0][y * frame->linesize[0] + x] = x + y + i *

> 3;

> > +            }

> > +        }

> > +

> > +        /* Cb and Cr */

> > +        for (y = 0; y < c->height/2; y++) {

> > +            for (x = 0; x < c->width/2; x++) {

> > +                frame->data[1][y * frame->linesize[1] + 2 * x] = 128 +

> y + i * 2;

> > +                frame->data[1][y * frame->linesize[1] + 2 * x + 1] = 64

> + x + i * 5;

> > +            }

> > +        }

> > +

> > +        frame->pts = i;

> > +

> > +        /* encode the image */

> > +        encode(c, frame, pkt, f);

> > +    }

> > +

> > +    /* flush the encoder */

> > +    encode(c, NULL, pkt, f);

> > +

> > +    fclose(f);

> > +

> > +    avcodec_free_context(&c);

> > +    av_frame_free(&frame);

> > +    av_packet_free(&pkt);

> > +    av_buffer_unref(&encode_device);

> > +

> > +    return 0;

> > +}

> > --

> > 1.8.3.1

> >

> > _______________________________________________

> > ffmpeg-devel mailing list

> > ffmpeg-devel@ffmpeg.org

> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

> _______________________________________________

> ffmpeg-devel mailing list

> ffmpeg-devel@ffmpeg.org

> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Steven Liu Aug. 7, 2017, 3:48 a.m. UTC | #3
2017-08-07 10:45 GMT+08:00 Li, Zhong <zhong.li@intel.com>:
>> -----Original Message-----
>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf
>> Of Steven Liu
>> Sent: Wednesday, August 2, 2017 2:01 PM
>> To: FFmpeg development discussions and patches
>> <ffmpeg-devel@ffmpeg.org>
>> Subject: Re: [FFmpeg-devel] [PATCH V2] doc/examples: Add a qsv encoder
>> example
>>
>> 2017-08-03 1:27 GMT+08:00 Zhong Li <zhong.li@intel.com>:
>> > It is an evolution from the exmaple "encode_video.c" to support qsv
>> encoder.
>> >
>> > V1->V2: Split to a separated qsv encoding example, instead of a patch
>> > based on encode_video.c
>> >
>> > Signed-off-by: Zhong Li <zhong.li@intel.com>
>> > ---
>> >  configure             |   2 +
>> >  doc/Makefile          |   1 +
>> >  doc/examples/qsvenc.c | 211
>> > ++++++++++++++++++++++++++++++++++++++++++++++++++
>> >  3 files changed, 214 insertions(+)
>> >  create mode 100644 doc/examples/qsvenc.c
>> >
>> > diff --git a/configure b/configure
>> > index 66c7b94..676cd85 100755
>> > --- a/configure
>> > +++ b/configure
>> > @@ -1472,6 +1472,7 @@ EXAMPLE_LIST="
>> >      metadata_example
>> >      muxing_example
>> >      qsvdec_example
>> > +    qsvenc_example
>> >      remuxing_example
>> >      resampling_audio_example
>> >      scaling_video_example
>> > @@ -3213,6 +3214,7 @@ hw_decode_example_deps="avcodec avformat
>> avutil"
>> >  metadata_example_deps="avformat avutil"
>> >  muxing_example_deps="avcodec avformat avutil swscale"
>> >  qsvdec_example_deps="avcodec avutil libmfx h264_qsv_decoder"
>> > +qsvenc_example_deps="avcodec avutil libmfx"
>> >  remuxing_example_deps="avcodec avformat avutil"
>> >  resampling_audio_example_deps="avutil swresample"
>> >  scaling_video_example_deps="avutil swscale"
>> > diff --git a/doc/Makefile b/doc/Makefile index b670f0b..ed41763 100644
>> > --- a/doc/Makefile
>> > +++ b/doc/Makefile
>> > @@ -52,6 +52,7 @@ DOC_EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE)
>> += hw_decode
>> >  DOC_EXAMPLES-$(CONFIG_METADATA_EXAMPLE)          +=
>> metadata
>> >  DOC_EXAMPLES-$(CONFIG_MUXING_EXAMPLE)            +=
>> muxing
>> >  DOC_EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE)            += qsvdec
>> > +DOC_EXAMPLES-$(CONFIG_QSVENC_EXAMPLE)            += qsvenc
>> >  DOC_EXAMPLES-$(CONFIG_REMUXING_EXAMPLE)          +=
>> remuxing
>> >  DOC_EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE)  +=
>> resampling_audio
>> >  DOC_EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE)     +=
>> scaling_video
>> > diff --git a/doc/examples/qsvenc.c b/doc/examples/qsvenc.c new file
>> > mode 100644 index 0000000..3b94cc8
>> > --- /dev/null
>> > +++ b/doc/examples/qsvenc.c
>> > @@ -0,0 +1,211 @@
>> > +/*
>> > + * Copyright (c) 2017 Fabrice Bellard, Zhong Li
>> > + *
>> > + * Permission is hereby granted, free of charge, to any person
>> > +obtaining a copy
>> > + * of this software and associated documentation files (the
>> > +"Software"), to deal
>> > + * in the Software without restriction, including without limitation
>> > +the rights
>> > + * to use, copy, modify, merge, publish, distribute, sublicense,
>> > +and/or sell
>> > + * copies of the Software, and to permit persons to whom the Software
>> > +is
>> > + * furnished to do so, subject to the following conditions:
>> > + *
>> > + * The above copyright notice and this permission notice shall be
>> > +included in
>> > + * all copies or substantial portions of the Software.
>> > + *
>> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
>> KIND,
>> > +EXPRESS OR
>> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> > +MERCHANTABILITY,
>> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
>> EVENT
>> > +SHALL
>> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
>> DAMAGES
>> > +OR OTHER
>> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
>> OTHERWISE,
>> > +ARISING FROM,
>> > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>> OTHER
>> > +DEALINGS IN
>> > + * THE SOFTWARE.
>> > + */
>> > +
>> > +/**
>> > + * @file
>> > + * Intel QSV-accelerated encoding example
>> > + *
>> > + * @example qsvenc.c
>> > + */
>> > +
>> > +#include <stdio.h>
>> > +#include <stdlib.h>
>> > +#include <string.h>
>> > +
>> > +#include <libavcodec/avcodec.h>
>> > +
>> > +#include <libavutil/opt.h>
>> > +#include <libavutil/imgutils.h>
>> > +#include "libavutil/buffer.h"
>> > +#include "libavutil/hwcontext.h"
>> > +
>> > +static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket
>> *pkt,
>> > +                   FILE *outfile)
>> > +{
>> > +    int ret;
>> > +
>> > +    /* send the frame to the encoder */
>> > +    if (frame)
>> > +        printf("Send frame %3"PRId64"\n", frame->pts);
>> > +
>> > +    ret = avcodec_send_frame(enc_ctx, frame);
>> > +    if (ret < 0) {
>> > +        fprintf(stderr, "Error sending a frame for encoding\n");
>> > +        exit(1);
>> > +    }
>> > +
>> > +    while (ret >= 0) {
>> > +        ret = avcodec_receive_packet(enc_ctx, pkt);
>> > +        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
>> > +            return;
>> > +        else if (ret < 0) {
>> > +            fprintf(stderr, "Error during encoding\n");
>> > +            exit(1);
>> > +        }
>> > +
>> > +        printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts,
>> pkt->size);
>> > +        fwrite(pkt->data, 1, pkt->size, outfile);
>> > +        av_packet_unref(pkt);
>> > +    }
>> > +}
>> > +
>> > +int main(int argc, char **argv)
>> > +{
>> > +    const char *filename, *codec_name;
>> > +    const AVCodec *codec;
>> > +    AVCodecContext *c= NULL;
>> Why don't use AVCodecParameters?
>
> Could you give more detail about the reason?
> AVCodecParameters is used for encoded bitstream. Here just encoding a raw yuv, seems AVCodecContext is enough.
Ah,  i know why now, Thanks :)
>
>> > +    int i, ret, x, y;
>> > +    FILE *f;
>> > +    AVFrame *frame;
>> > +    AVPacket *pkt;
>> > +    AVBufferRef *encode_device = NULL;
>> > +
>> > +    if (argc <= 2) {
>> > +        fprintf(stderr, "Usage: %s <output file> <codec name>\n",
>> argv[0]);
>> > +        exit(0);
>> > +    }
>> > +    filename = argv[1];
>> > +    codec_name = argv[2];
>> > +
>> > +    if (!strstr(codec_name, "qsv")) {
>> > +        fprintf(stderr, "no qsv codec found\n");
>> > +        exit(0);
>> > +    }
>> > +
>> > +    avcodec_register_all();
>> > +
>> > +    /* open the qsv hardware device */
>> > +    ret = av_hwdevice_ctx_create(&encode_device,
>> AV_HWDEVICE_TYPE_QSV,
>> > +                                 NULL, NULL, 0);
>> > +    if (ret < 0) {
>> > +        fprintf(stderr, "Cannot open the hardware device\n");
>> > +        exit(1);
>> > +    }
>> > +
>> > +    /* find the encoder */
>> > +    codec = avcodec_find_encoder_by_name(codec_name);
>> > +    if (!codec) {
>> > +        fprintf(stderr, "Codec '%s' not found\n", codec_name);
>> > +        exit(1);
>> > +    }
>> > +
>> > +    c = avcodec_alloc_context3(codec);
>> > +    if (!c) {
>> > +        fprintf(stderr, "Could not allocate video codec context\n");
>> > +        exit(1);
>> > +    }
>> > +
>> > +    pkt = av_packet_alloc();
>> > +    if (!pkt)
>> > +        exit(1);
>> > +
>> > +    /* put sample parameters */
>> > +    c->bit_rate = 400000;
>> > +    /* resolution must be a multiple of two */
>> > +    c->width = 352;
>> > +    c->height = 288;
>> > +    /* frames per second */
>> > +    c->time_base = (AVRational){1, 25};
>> > +    c->framerate = (AVRational){25, 1};
>> > +
>> > +    /* emit one intra frame every ten frames
>> > +     * check frame pict_type before passing frame
>> > +     * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
>> > +     * then gop_size is ignored and the output of encoder
>> > +     * will always be I frame irrespective to gop_size
>> > +     */
>> > +    c->gop_size = 10;
>> > +    c->max_b_frames = 1;
>> > +    c->pix_fmt = AV_PIX_FMT_NV12;
>> > +    c->hw_device_ctx = av_buffer_ref(encode_device);
>> > +
>> > +    /* open it */
>> > +    ret = avcodec_open2(c, codec, NULL);
>> > +    if (ret < 0) {
>> > +        fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
>> > +        exit(1);
>> > +    }
>> > +
>> > +    f = fopen(filename, "wb");
>> > +    if (!f) {
>> > +        fprintf(stderr, "Could not open %s\n", filename);
>> > +        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;
>> > +
>> > +    ret = av_frame_get_buffer(frame, 32);
>> > +    if (ret < 0) {
>> > +        fprintf(stderr, "Could not allocate the video frame data\n");
>> > +        exit(1);
>> > +    }
>> > +
>> > +    /* encode 1 second of video */
>> > +    for (i = 0; i < 25; i++) {
>> > +        fflush(stdout);
>> > +
>> > +        /* make sure the frame data is writable */
>> > +        ret = av_frame_make_writable(frame);
>> > +        if (ret < 0)
>> > +            exit(1);
>> > +
>> > +        /* prepare a dummy image */
>> > +        /* Y */
>> > +        for (y = 0; y < c->height; y++) {
>> > +            for (x = 0; x < c->width; x++) {
>> > +                frame->data[0][y * frame->linesize[0] + x] = x + y + i *
>> 3;
>> > +            }
>> > +        }
>> > +
>> > +        /* Cb and Cr */
>> > +        for (y = 0; y < c->height/2; y++) {
>> > +            for (x = 0; x < c->width/2; x++) {
>> > +                frame->data[1][y * frame->linesize[1] + 2 * x] = 128 +
>> y + i * 2;
>> > +                frame->data[1][y * frame->linesize[1] + 2 * x + 1] = 64
>> + x + i * 5;
>> > +            }
>> > +        }
>> > +
>> > +        frame->pts = i;
>> > +
>> > +        /* encode the image */
>> > +        encode(c, frame, pkt, f);
>> > +    }
>> > +
>> > +    /* flush the encoder */
>> > +    encode(c, NULL, pkt, f);
>> > +
>> > +    fclose(f);
>> > +
>> > +    avcodec_free_context(&c);
>> > +    av_frame_free(&frame);
>> > +    av_packet_free(&pkt);
>> > +    av_buffer_unref(&encode_device);
>> > +
>> > +    return 0;
>> > +}
>> > --
>> > 1.8.3.1
>> >
>> > _______________________________________________
>> > ffmpeg-devel mailing list
>> > ffmpeg-devel@ffmpeg.org
>> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Zhong Li Aug. 16, 2017, 6:54 a.m. UTC | #4
> -----Original Message-----

> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf

> Of Steven Liu

> Sent: Monday, August 7, 2017 11:49 AM

> To: FFmpeg development discussions and patches

> <ffmpeg-devel@ffmpeg.org>

> Subject: Re: [FFmpeg-devel] [PATCH V2] doc/examples: Add a qsv encoder

> example

> 

> 2017-08-07 10:45 GMT+08:00 Li, Zhong <zhong.li@intel.com>:

> >> -----Original Message-----

> >> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On

> Behalf

> >> Of Steven Liu

> >> Sent: Wednesday, August 2, 2017 2:01 PM

> >> To: FFmpeg development discussions and patches

> >> <ffmpeg-devel@ffmpeg.org>

> >> Subject: Re: [FFmpeg-devel] [PATCH V2] doc/examples: Add a qsv

> >> encoder example

> >>

> >> 2017-08-03 1:27 GMT+08:00 Zhong Li <zhong.li@intel.com>:

> >> > It is an evolution from the exmaple "encode_video.c" to support qsv

> >> encoder.

> >> >

> >> > V1->V2: Split to a separated qsv encoding example, instead of a

> >> > V1->patch

> >> > based on encode_video.c

> >> >

> >> > Signed-off-by: Zhong Li <zhong.li@intel.com>

> >> > ---

> >> >  configure             |   2 +

> >> >  doc/Makefile          |   1 +

> >> >  doc/examples/qsvenc.c | 211

> >> > ++++++++++++++++++++++++++++++++++++++++++++++++++

> >> >  3 files changed, 214 insertions(+)  create mode 100644

> >> > doc/examples/qsvenc.c

> >> >

> >> > diff --git a/configure b/configure

> >> > index 66c7b94..676cd85 100755

> >> > --- a/configure

> >> > +++ b/configure

> >> > @@ -1472,6 +1472,7 @@ EXAMPLE_LIST="

> >> >      metadata_example

> >> >      muxing_example

> >> >      qsvdec_example

> >> > +    qsvenc_example

> >> >      remuxing_example

> >> >      resampling_audio_example

> >> >      scaling_video_example

> >> > @@ -3213,6 +3214,7 @@ hw_decode_example_deps="avcodec

> avformat

> >> avutil"

> >> >  metadata_example_deps="avformat avutil"

> >> >  muxing_example_deps="avcodec avformat avutil swscale"

> >> >  qsvdec_example_deps="avcodec avutil libmfx h264_qsv_decoder"

> >> > +qsvenc_example_deps="avcodec avutil libmfx"

> >> >  remuxing_example_deps="avcodec avformat avutil"

> >> >  resampling_audio_example_deps="avutil swresample"

> >> >  scaling_video_example_deps="avutil swscale"

> >> > diff --git a/doc/Makefile b/doc/Makefile index b670f0b..ed41763

> >> > 100644

> >> > --- a/doc/Makefile

> >> > +++ b/doc/Makefile

> >> > @@ -52,6 +52,7 @@

> DOC_EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE)

> >> += hw_decode

> >> >  DOC_EXAMPLES-$(CONFIG_METADATA_EXAMPLE)          +=

> >> metadata

> >> >  DOC_EXAMPLES-$(CONFIG_MUXING_EXAMPLE)            +=

> >> muxing

> >> >  DOC_EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE)            +=

> qsvdec

> >> > +DOC_EXAMPLES-$(CONFIG_QSVENC_EXAMPLE)            +=

> qsvenc

> >> >  DOC_EXAMPLES-$(CONFIG_REMUXING_EXAMPLE)          +=

> >> remuxing

> >> >  DOC_EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE)  +=

> >> resampling_audio

> >> >  DOC_EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE)     +=

> >> scaling_video

> >> > diff --git a/doc/examples/qsvenc.c b/doc/examples/qsvenc.c new file

> >> > mode 100644 index 0000000..3b94cc8

> >> > --- /dev/null

> >> > +++ b/doc/examples/qsvenc.c

> >> > @@ -0,0 +1,211 @@

> >> > +/*

> >> > + * Copyright (c) 2017 Fabrice Bellard, Zhong Li

> >> > + *

> >> > + * Permission is hereby granted, free of charge, to any person

> >> > +obtaining a copy

> >> > + * of this software and associated documentation files (the

> >> > +"Software"), to deal

> >> > + * in the Software without restriction, including without

> >> > +limitation the rights

> >> > + * to use, copy, modify, merge, publish, distribute, sublicense,

> >> > +and/or sell

> >> > + * copies of the Software, and to permit persons to whom the

> >> > +Software is

> >> > + * furnished to do so, subject to the following conditions:

> >> > + *

> >> > + * The above copyright notice and this permission notice shall be

> >> > +included in

> >> > + * all copies or substantial portions of the Software.

> >> > + *

> >> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY

> >> KIND,

> >> > +EXPRESS OR

> >> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF

> >> > +MERCHANTABILITY,

> >> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN

> NO

> >> EVENT

> >> > +SHALL

> >> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,

> >> DAMAGES

> >> > +OR OTHER

> >> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR

> >> OTHERWISE,

> >> > +ARISING FROM,

> >> > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR

> >> OTHER

> >> > +DEALINGS IN

> >> > + * THE SOFTWARE.

> >> > + */

> >> > +

> >> > +/**

> >> > + * @file

> >> > + * Intel QSV-accelerated encoding example

> >> > + *

> >> > + * @example qsvenc.c

> >> > + */

> >> > +

> >> > +#include <stdio.h>

> >> > +#include <stdlib.h>

> >> > +#include <string.h>

> >> > +

> >> > +#include <libavcodec/avcodec.h>

> >> > +

> >> > +#include <libavutil/opt.h>

> >> > +#include <libavutil/imgutils.h>

> >> > +#include "libavutil/buffer.h"

> >> > +#include "libavutil/hwcontext.h"

> >> > +

> >> > +static void encode(AVCodecContext *enc_ctx, AVFrame *frame,

> >> > +AVPacket

> >> *pkt,

> >> > +                   FILE *outfile)

> >> > +{

> >> > +    int ret;

> >> > +

> >> > +    /* send the frame to the encoder */

> >> > +    if (frame)

> >> > +        printf("Send frame %3"PRId64"\n", frame->pts);

> >> > +

> >> > +    ret = avcodec_send_frame(enc_ctx, frame);

> >> > +    if (ret < 0) {

> >> > +        fprintf(stderr, "Error sending a frame for encoding\n");

> >> > +        exit(1);

> >> > +    }

> >> > +

> >> > +    while (ret >= 0) {

> >> > +        ret = avcodec_receive_packet(enc_ctx, pkt);

> >> > +        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)

> >> > +            return;

> >> > +        else if (ret < 0) {

> >> > +            fprintf(stderr, "Error during encoding\n");

> >> > +            exit(1);

> >> > +        }

> >> > +

> >> > +        printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts,

> >> pkt->size);

> >> > +        fwrite(pkt->data, 1, pkt->size, outfile);

> >> > +        av_packet_unref(pkt);

> >> > +    }

> >> > +}

> >> > +

> >> > +int main(int argc, char **argv)

> >> > +{

> >> > +    const char *filename, *codec_name;

> >> > +    const AVCodec *codec;

> >> > +    AVCodecContext *c= NULL;

> >> Why don't use AVCodecParameters?

> >

> > Could you give more detail about the reason?

> > AVCodecParameters is used for encoded bitstream. Here just encoding a

> raw yuv, seems AVCodecContext is enough.

> Ah,  i know why now, Thanks :)


Any other comment about this patch? How it can be merged?
> >

> >> > +    int i, ret, x, y;

> >> > +    FILE *f;

> >> > +    AVFrame *frame;

> >> > +    AVPacket *pkt;

> >> > +    AVBufferRef *encode_device = NULL;

> >> > +

> >> > +    if (argc <= 2) {

> >> > +        fprintf(stderr, "Usage: %s <output file> <codec name>\n",

> >> argv[0]);

> >> > +        exit(0);

> >> > +    }

> >> > +    filename = argv[1];

> >> > +    codec_name = argv[2];

> >> > +

> >> > +    if (!strstr(codec_name, "qsv")) {

> >> > +        fprintf(stderr, "no qsv codec found\n");

> >> > +        exit(0);

> >> > +    }

> >> > +

> >> > +    avcodec_register_all();

> >> > +

> >> > +    /* open the qsv hardware device */

> >> > +    ret = av_hwdevice_ctx_create(&encode_device,

> >> AV_HWDEVICE_TYPE_QSV,

> >> > +                                 NULL, NULL, 0);

> >> > +    if (ret < 0) {

> >> > +        fprintf(stderr, "Cannot open the hardware device\n");

> >> > +        exit(1);

> >> > +    }

> >> > +

> >> > +    /* find the encoder */

> >> > +    codec = avcodec_find_encoder_by_name(codec_name);

> >> > +    if (!codec) {

> >> > +        fprintf(stderr, "Codec '%s' not found\n", codec_name);

> >> > +        exit(1);

> >> > +    }

> >> > +

> >> > +    c = avcodec_alloc_context3(codec);

> >> > +    if (!c) {

> >> > +        fprintf(stderr, "Could not allocate video codec context\n");

> >> > +        exit(1);

> >> > +    }

> >> > +

> >> > +    pkt = av_packet_alloc();

> >> > +    if (!pkt)

> >> > +        exit(1);

> >> > +

> >> > +    /* put sample parameters */

> >> > +    c->bit_rate = 400000;

> >> > +    /* resolution must be a multiple of two */

> >> > +    c->width = 352;

> >> > +    c->height = 288;

> >> > +    /* frames per second */

> >> > +    c->time_base = (AVRational){1, 25};

> >> > +    c->framerate = (AVRational){25, 1};

> >> > +

> >> > +    /* emit one intra frame every ten frames

> >> > +     * check frame pict_type before passing frame

> >> > +     * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I

> >> > +     * then gop_size is ignored and the output of encoder

> >> > +     * will always be I frame irrespective to gop_size

> >> > +     */

> >> > +    c->gop_size = 10;

> >> > +    c->max_b_frames = 1;

> >> > +    c->pix_fmt = AV_PIX_FMT_NV12;

> >> > +    c->hw_device_ctx = av_buffer_ref(encode_device);

> >> > +

> >> > +    /* open it */

> >> > +    ret = avcodec_open2(c, codec, NULL);

> >> > +    if (ret < 0) {

> >> > +        fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));

> >> > +        exit(1);

> >> > +    }

> >> > +

> >> > +    f = fopen(filename, "wb");

> >> > +    if (!f) {

> >> > +        fprintf(stderr, "Could not open %s\n", filename);

> >> > +        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;

> >> > +

> >> > +    ret = av_frame_get_buffer(frame, 32);

> >> > +    if (ret < 0) {

> >> > +        fprintf(stderr, "Could not allocate the video frame data\n");

> >> > +        exit(1);

> >> > +    }

> >> > +

> >> > +    /* encode 1 second of video */

> >> > +    for (i = 0; i < 25; i++) {

> >> > +        fflush(stdout);

> >> > +

> >> > +        /* make sure the frame data is writable */

> >> > +        ret = av_frame_make_writable(frame);

> >> > +        if (ret < 0)

> >> > +            exit(1);

> >> > +

> >> > +        /* prepare a dummy image */

> >> > +        /* Y */

> >> > +        for (y = 0; y < c->height; y++) {

> >> > +            for (x = 0; x < c->width; x++) {

> >> > +                frame->data[0][y * frame->linesize[0] + x] = x + y

> >> > + + i *

> >> 3;

> >> > +            }

> >> > +        }

> >> > +

> >> > +        /* Cb and Cr */

> >> > +        for (y = 0; y < c->height/2; y++) {

> >> > +            for (x = 0; x < c->width/2; x++) {

> >> > +                frame->data[1][y * frame->linesize[1] + 2 * x] =

> >> > + 128 +

> >> y + i * 2;

> >> > +                frame->data[1][y * frame->linesize[1] + 2 * x + 1]

> >> > + = 64

> >> + x + i * 5;

> >> > +            }

> >> > +        }

> >> > +

> >> > +        frame->pts = i;

> >> > +

> >> > +        /* encode the image */

> >> > +        encode(c, frame, pkt, f);

> >> > +    }

> >> > +

> >> > +    /* flush the encoder */

> >> > +    encode(c, NULL, pkt, f);

> >> > +

> >> > +    fclose(f);

> >> > +

> >> > +    avcodec_free_context(&c);

> >> > +    av_frame_free(&frame);

> >> > +    av_packet_free(&pkt);

> >> > +    av_buffer_unref(&encode_device);

> >> > +

> >> > +    return 0;

> >> > +}

> >> > --

> >> > 1.8.3.1

> >> >

> >> > _______________________________________________

> >> > ffmpeg-devel mailing list

> >> > ffmpeg-devel@ffmpeg.org

> >> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

> >> _______________________________________________

> >> ffmpeg-devel mailing list

> >> ffmpeg-devel@ffmpeg.org

> >> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

> > _______________________________________________

> > ffmpeg-devel mailing list

> > ffmpeg-devel@ffmpeg.org

> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

> _______________________________________________

> ffmpeg-devel mailing list

> ffmpeg-devel@ffmpeg.org

> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
diff mbox

Patch

diff --git a/configure b/configure
index 66c7b94..676cd85 100755
--- a/configure
+++ b/configure
@@ -1472,6 +1472,7 @@  EXAMPLE_LIST="
     metadata_example
     muxing_example
     qsvdec_example
+    qsvenc_example
     remuxing_example
     resampling_audio_example
     scaling_video_example
@@ -3213,6 +3214,7 @@  hw_decode_example_deps="avcodec avformat avutil"
 metadata_example_deps="avformat avutil"
 muxing_example_deps="avcodec avformat avutil swscale"
 qsvdec_example_deps="avcodec avutil libmfx h264_qsv_decoder"
+qsvenc_example_deps="avcodec avutil libmfx"
 remuxing_example_deps="avcodec avformat avutil"
 resampling_audio_example_deps="avutil swresample"
 scaling_video_example_deps="avutil swscale"
diff --git a/doc/Makefile b/doc/Makefile
index b670f0b..ed41763 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -52,6 +52,7 @@  DOC_EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE)         += hw_decode
 DOC_EXAMPLES-$(CONFIG_METADATA_EXAMPLE)          += metadata
 DOC_EXAMPLES-$(CONFIG_MUXING_EXAMPLE)            += muxing
 DOC_EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE)            += qsvdec
+DOC_EXAMPLES-$(CONFIG_QSVENC_EXAMPLE)            += qsvenc
 DOC_EXAMPLES-$(CONFIG_REMUXING_EXAMPLE)          += remuxing
 DOC_EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE)  += resampling_audio
 DOC_EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE)     += scaling_video
diff --git a/doc/examples/qsvenc.c b/doc/examples/qsvenc.c
new file mode 100644
index 0000000..3b94cc8
--- /dev/null
+++ b/doc/examples/qsvenc.c
@@ -0,0 +1,211 @@ 
+/*
+ * Copyright (c) 2017 Fabrice Bellard, Zhong Li
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @file
+ * Intel QSV-accelerated encoding example
+ *
+ * @example qsvenc.c
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libavcodec/avcodec.h>
+
+#include <libavutil/opt.h>
+#include <libavutil/imgutils.h>
+#include "libavutil/buffer.h"
+#include "libavutil/hwcontext.h"
+
+static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,
+                   FILE *outfile)
+{
+    int ret;
+
+    /* send the frame to the encoder */
+    if (frame)
+        printf("Send frame %3"PRId64"\n", frame->pts);
+
+    ret = avcodec_send_frame(enc_ctx, frame);
+    if (ret < 0) {
+        fprintf(stderr, "Error sending a frame for encoding\n");
+        exit(1);
+    }
+
+    while (ret >= 0) {
+        ret = avcodec_receive_packet(enc_ctx, pkt);
+        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+            return;
+        else if (ret < 0) {
+            fprintf(stderr, "Error during encoding\n");
+            exit(1);
+        }
+
+        printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);
+        fwrite(pkt->data, 1, pkt->size, outfile);
+        av_packet_unref(pkt);
+    }
+}
+
+int main(int argc, char **argv)
+{
+    const char *filename, *codec_name;
+    const AVCodec *codec;
+    AVCodecContext *c= NULL;
+    int i, ret, x, y;
+    FILE *f;
+    AVFrame *frame;
+    AVPacket *pkt;
+    AVBufferRef *encode_device = NULL;
+
+    if (argc <= 2) {
+        fprintf(stderr, "Usage: %s <output file> <codec name>\n", argv[0]);
+        exit(0);
+    }
+    filename = argv[1];
+    codec_name = argv[2];
+
+    if (!strstr(codec_name, "qsv")) {
+        fprintf(stderr, "no qsv codec found\n");
+        exit(0);
+    }
+
+    avcodec_register_all();
+
+    /* open the qsv hardware device */
+    ret = av_hwdevice_ctx_create(&encode_device, AV_HWDEVICE_TYPE_QSV,
+                                 NULL, NULL, 0);
+    if (ret < 0) {
+        fprintf(stderr, "Cannot open the hardware device\n");
+        exit(1);
+    }
+
+    /* find the encoder */
+    codec = avcodec_find_encoder_by_name(codec_name);
+    if (!codec) {
+        fprintf(stderr, "Codec '%s' not found\n", codec_name);
+        exit(1);
+    }
+
+    c = avcodec_alloc_context3(codec);
+    if (!c) {
+        fprintf(stderr, "Could not allocate video codec context\n");
+        exit(1);
+    }
+
+    pkt = av_packet_alloc();
+    if (!pkt)
+        exit(1);
+
+    /* put sample parameters */
+    c->bit_rate = 400000;
+    /* resolution must be a multiple of two */
+    c->width = 352;
+    c->height = 288;
+    /* frames per second */
+    c->time_base = (AVRational){1, 25};
+    c->framerate = (AVRational){25, 1};
+
+    /* emit one intra frame every ten frames
+     * check frame pict_type before passing frame
+     * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
+     * then gop_size is ignored and the output of encoder
+     * will always be I frame irrespective to gop_size
+     */
+    c->gop_size = 10;
+    c->max_b_frames = 1;
+    c->pix_fmt = AV_PIX_FMT_NV12;
+    c->hw_device_ctx = av_buffer_ref(encode_device);
+
+    /* open it */
+    ret = avcodec_open2(c, codec, NULL);
+    if (ret < 0) {
+        fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
+        exit(1);
+    }
+
+    f = fopen(filename, "wb");
+    if (!f) {
+        fprintf(stderr, "Could not open %s\n", filename);
+        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;
+
+    ret = av_frame_get_buffer(frame, 32);
+    if (ret < 0) {
+        fprintf(stderr, "Could not allocate the video frame data\n");
+        exit(1);
+    }
+
+    /* encode 1 second of video */
+    for (i = 0; i < 25; i++) {
+        fflush(stdout);
+
+        /* make sure the frame data is writable */
+        ret = av_frame_make_writable(frame);
+        if (ret < 0)
+            exit(1);
+
+        /* prepare a dummy image */
+        /* Y */
+        for (y = 0; y < c->height; y++) {
+            for (x = 0; x < c->width; x++) {
+                frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
+            }
+        }
+
+        /* Cb and Cr */
+        for (y = 0; y < c->height/2; y++) {
+            for (x = 0; x < c->width/2; x++) {
+                frame->data[1][y * frame->linesize[1] + 2 * x] = 128 + y + i * 2;
+                frame->data[1][y * frame->linesize[1] + 2 * x + 1] = 64 + x + i * 5;
+            }
+        }
+
+        frame->pts = i;
+
+        /* encode the image */
+        encode(c, frame, pkt, f);
+    }
+
+    /* flush the encoder */
+    encode(c, NULL, pkt, f);
+
+    fclose(f);
+
+    avcodec_free_context(&c);
+    av_frame_free(&frame);
+    av_packet_free(&pkt);
+    av_buffer_unref(&encode_device);
+
+    return 0;
+}