[FFmpeg-devel] patch for a new H.264 codec

Submitted by Yufei He on Feb. 25, 2019, 8:41 p.m.

Details

Message ID 9147cf5e-5ff5-08ad-d8da-0eb0fb8f5925@matrox.com
State New
Headers show

Commit Message

Yufei He Feb. 25, 2019, 8:41 p.m.
Hi

Please review this one.

Thanks.

Yufei.


On 02/25/2019 02:58 PM, Nicolas George wrote:

Yufei He (12019-02-25):


From 7dd17409a22858f3c18d832c301fb904508dea3b Mon Sep 17 00:00:00 2001
From: yhe <yhe@matrox.com><mailto:yhe@matrox.com>

Date: Mon, 25 Feb 2019 14:38:21 -0500
Subject: [PATCH] M264 codec support



Quick comments.

They are in no way to be taken as any kind of endorsement for the patch.




---
 .vscode/settings.json            |  27 +++



No, thanks.



 Changelog                        |   1 +
 configure                        |   1 +
 doc/general.texi                 |   1 +
 fftools/ffmpeg.c                 |  14 ++
 libavcodec/.vscode/settings.json |   5 +
 libavcodec/Makefile              |   5 +
 libavcodec/allcodecs.c           |   6 +-
 libavcodec/avcodec.h             |   3 +
 libavcodec/codec_desc.c          |   9 +
 libavcodec/m264dec.c             | 476 +++++++++++++++++++++++++++++++++++++++
 libavcodec/m264dec.h             |  42 ++++
 libavcodec/m264enc.c             | 289 ++++++++++++++++++++++++
 libavcodec/m264enc.h             |  39 ++++
 libavcodec/profiles.c            |   5 +
 libavcodec/profiles.h            |   1 +
 16 files changed, 922 insertions(+), 2 deletions(-)
 create mode 100644 .vscode/settings.json
 create mode 100644 libavcodec/.vscode/settings.json
 create mode 100644 libavcodec/m264dec.c
 create mode 100644 libavcodec/m264dec.h
 create mode 100644 libavcodec/m264enc.c
 create mode 100644 libavcodec/m264enc.h



+extern const AVProfile ff_m264_profiles[];



Unused.




 #endif /* AVCODEC_PROFILES_H */



Regards,





_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org<mailto:ffmpeg-devel@ffmpeg.org>
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Comments

Carl Eugen Hoyos March 11, 2019, 12:59 a.m.
2019-02-25 21:41 GMT+01:00, Yufei He <yhe@matrox.com>:

> Please review this one.

The library needs non-free in configure and please
use dynamic linking, not loading at run-time.

Please find out what top-posting means and avoid it here, Carl Eugen
Moritz Barsnick March 11, 2019, 8:53 a.m.
On Mon, Mar 11, 2019 at 01:59:47 +0100, Carl Eugen Hoyos wrote:
> The library needs non-free in configure and please
> use dynamic linking, not loading at run-time.

There is also no indication whatsoever where to get mvM264Ffmpeg.dll
and libmvM264Ffmpeg.so from. No-one can even attempt to run (or - once
you, Yufei, have fixed it - compile) this functionality without this.
That's hopeless.

Moritz
Ronald S. Bultje March 11, 2019, 10:57 a.m.
Hi,

On Mon, Mar 11, 2019 at 4:53 AM Moritz Barsnick <barsnick@gmx.net> wrote:

> On Mon, Mar 11, 2019 at 01:59:47 +0100, Carl Eugen Hoyos wrote:
> > The library needs non-free in configure and please
> > use dynamic linking, not loading at run-time.
>
> There is also no indication whatsoever where to get mvM264Ffmpeg.dll
> and libmvM264Ffmpeg.so from. No-one can even attempt to run (or - once
> you, Yufei, have fixed it - compile) this functionality without this.
> That's hopeless.
>

I want to reiterate my point from the other thread here that I think it's
time that we set an official project policy w.r.t. closed-source software.

I believe we should either choose that there is no place in FFmpeg for this
sort of things (I support this point of view), or we should set specific
guidelines about the software (I understand some developers lean more
towards this, and I respect that). Right now it's all random and that's not
good.

- How do we set up a fate station with m264 support? Or will matrox provide
one? Or will it be available to FFmpeg developers at no charge?
- How do we test that it still works after we make innocent changes to some
API?
- If we add new H264 files to our conformance suite, how do we confirm that
m264dec passes them?
- If we see particular optimizations or code changes that would make this
wrapper work better, how do we test that it still works? (If we can't, then
is the wrapper truly open source software?)
Etc.

Ronald
Carl Eugen Hoyos March 11, 2019, 11:04 a.m.
2019-03-11 11:57 GMT+01:00, Ronald S. Bultje <rsbultje@gmail.com>:

> - How do we set up a fate station with m264 support?

We do not test any external libraries with fate.

[...]

> - How do we test that it still works after we make innocent
> changes to some API?

Same as so far: We remove the feature that isn't updated.

> - If we add new H264 files to our conformance suite, how
> do we confirm that m264dec passes them?

That wouldn't work for any of our external codecs (at least
for some it wouldn't), in some cases the reason is that
the external codec supports things unsupported by FFmpeg,
in some cases there are license issues even with
open-source software.

Sorry, but some of this sounds like a solution in search of a
problem.

No strong opinion here about Matrox but we accepted AMD
in spite of their mails, so I don't see why we can't accept a
non-free Matrox codec (as long as the patch is reasonably
clean).

Carl Eugen
Yufei He March 11, 2019, 1:53 p.m.
Hi Carl

Matrox M264 is similar to other hardware codecs.

I saw amf_load_library and nvenc_load_library in ffmpeg.

Matrox M264 is the same.

We got a lot customers using ffmpeg and they want to use Matrox M264 to do transcoding.

Thanks a lot.

Yufei.


static int amf_load_library(AVCodecContext *avctx)
{
AmfContext *ctx = avctx->priv_data;
AMFInit_Fn init_fun;
AMFQueryVersion_Fn version_fun;
AMF_RESULT res;
ctx->delayed_frame = av_frame_alloc();
if (!ctx->delayed_frame) {
return AVERROR(ENOMEM);
}
// hardcoded to current HW queue size - will realloc in timestamp_queue_enqueue() if too small
ctx->timestamp_list = av_fifo_alloc((avctx->max_b_frames + 16) * sizeof(int64_t));
if (!ctx->timestamp_list) {
return AVERROR(ENOMEM);
}
ctx->dts_delay = 0;
ctx->library = dlopen(AMF_DLL_NAMEA, RTLD_NOW | RTLD_LOCAL);
AMF_RETURN_IF_FALSE(ctx, ctx->library != NULL,
AVERROR_UNKNOWN, "DLL %s failed to open\n", AMF_DLL_NAMEA);
init_fun = (AMFInit_Fn)dlsym(ctx->library, AMF_INIT_FUNCTION_NAME);
AMF_RETURN_IF_FALSE(ctx, init_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_INIT_FUNCTION_NAME);
version_fun = (AMFQueryVersion_Fn)dlsym(ctx->library, AMF_QUERY_VERSION_FUNCTION_NAME);
AMF_RETURN_IF_FALSE(ctx, version_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_QUERY_VERSION_FUNCTION_NAME);


static av_cold int nvenc_load_libraries(AVCodecContext *avctx)
{
NvencContext *ctx = avctx->priv_data;
NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
NVENCSTATUS err;
uint32_t nvenc_max_ver;
int ret;
ret = cuda_load_functions(&dl_fn->cuda_dl, avctx);
if (ret < 0)
return ret;
ret = nvenc_load_functions(&dl_fn->nvenc_dl, avctx);
if (ret < 0) {
nvenc_print_driver_requirement(avctx, AV_LOG_ERROR);
return ret;
}
err = dl_fn->nvenc_dl->NvEncodeAPIGetMaxSupportedVersion(&nvenc_max_ver);
if (err != NV_ENC_SUCCESS)
return nvenc_print_error(avctx, err, "Failed to query nvenc max version");
av_log(avctx, AV_LOG_VERBOSE, "Loaded Nvenc version %d.%d\n", nvenc_max_ver >> 4, nvenc_max_ver & 0xf);
if ((NVENCAPI_MAJOR_VERSION << 4 | NVENCAPI_MINOR_VERSION) > nvenc_max_ver) {
av_log(avctx, AV_LOG_ERROR, "Driver does not support the required nvenc API version. "
"Required: %d.%d Found: %d.%d\n",
NVENCAPI_MAJOR_VERSION, NVENCAPI_MINOR_VERSION,
nvenc_max_ver >> 4, nvenc_max_ver & 0xf);
On 03/11/2019 07:04 AM, Carl Eugen Hoyos wrote:

2019-03-11 11:57 GMT+01:00, Ronald S. Bultje <rsbultje@gmail.com><mailto:rsbultje@gmail.com>:



- How do we set up a fate station with m264 support?



We do not test any external libraries with fate.

[...]



- How do we test that it still works after we make innocent
changes to some API?



Same as so far: We remove the feature that isn't updated.



- If we add new H264 files to our conformance suite, how
do we confirm that m264dec passes them?



That wouldn't work for any of our external codecs (at least
for some it wouldn't), in some cases the reason is that
the external codec supports things unsupported by FFmpeg,
in some cases there are license issues even with
open-source software.

Sorry, but some of this sounds like a solution in search of a
problem.

No strong opinion here about Matrox but we accepted AMD
in spite of their mails, so I don't see why we can't accept a
non-free Matrox codec (as long as the patch is reasonably
clean).

Carl Eugen
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org<mailto:ffmpeg-devel@ffmpeg.org>
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Nicolas George March 11, 2019, 1:55 p.m.
Yufei He (12019-03-11):
> Matrox M264 is similar to other hardware codecs.
> 
> I saw amf_load_library and nvenc_load_library in ffmpeg.

Past practices do not constitute precedents.

> We got a lot customers using ffmpeg and they want to use Matrox M264 to do transcoding.

If you make the driver GPL-compatible, there will be no problem at all.

Regards,
Soft Works March 11, 2019, 4:21 p.m.
> From: Nicolas George
>
> Yufei He (12019-03-11):
> > Matrox M264 is similar to other hardware codecs.
> >
> > I saw amf_load_library and nvenc_load_library in ffmpeg.
>
> Past practices do not constitute precedents.
>
> > We got a lot customers using ffmpeg and they want to use Matrox M264 to do transcoding.
>
> If you make the driver GPL-compatible, there will be no problem at all.
>
> Regards,
>
> --
>   Nicolas George

While I don’t care much about Matrox, I’m a bit surprised about the
recent sounds here. Should  we expect ffmpeg to drop most hw
accelerations, then?

IANAL, but aren’t drivers clearly considered to be system components?
In this case they would  be exempted from the GPL afaic?

Anyway, I thought that ffmpeg is LGPL, not GPL. It only becomes GPL
as soon as someone is including GPL libraries, right?

And in that case: wouldn’t it be true that only the owners of
such an included GPL component could pursue and make demands
against a potential violator (violating GPL but not LGPL terms)?

Since ffmpeg code is LGPL, my understanding is that ffmpeg could only
pursue violations of the license under which it is publishing its code,
and that would be LGPL but not GPL.


I’m just wondering – are those assumptions incorrect?

Regards,
softworkz
Jean-Baptiste Kempf March 11, 2019, 4:24 p.m.
On Mon, 11 Mar 2019, at 17:21, Soft Works wrote:
> While I don’t care much about Matrox, I’m a bit surprised about the
> recent sounds here. Should  we expect ffmpeg to drop most hw
> accelerations, then?

Absolutely not.

> IANAL, but aren’t drivers clearly considered to be system components?

Sure, but here, it does not seem to call a driver, but a specific library called libmvM264Ffmpeg that is being called.

Maybe this is just a mis-communication, though.
Soft Works March 11, 2019, 4:45 p.m.
> From: Jean-Baptiste Kempf
>
> On Mon, 11 Mar 2019, at 17:21, Soft Works wrote:
> > While I don’t care much about Matrox, I’m a bit surprised about the
> > recent sounds here. Should  we expect ffmpeg to drop most hw
> > accelerations, then?
>
> Absolutely not.

I very glad to hear that :-)

> > IANAL, but aren’t drivers clearly considered to be system components?
>
> Sure, but here, it does not seem to call a driver, but a specific library called libmvM264Ffmpeg that is being called.
>
> Maybe this is just a mis-communication, though.

Well, it probably was then, thanks for the clarification.

I came to think that it's hardware related because:

> Nicolas wrote:
>> If you make the driver GPL-compatible, there will be no problem at all.


I still wonder why recent discussions are often referring to GPL even though ffmpeg is released under LGPL.


Best regards,
softworkz
Jean-Baptiste Kempf March 11, 2019, 4:59 p.m.
On Mon, 11 Mar 2019, at 17:46, Soft Works wrote:
> I still wonder why recent discussions are often referring to GPL even 
> though ffmpeg is released under LGPL.

Because LGPL is a derivative of the GPL, unfortunately.
And there are a lot more jurisprudence on the GPL, than on the LGPL.
And LGPL has an upgradability clause to GPL.
Ronald S. Bultje March 11, 2019, 5:28 p.m.
Hi,

On Mon, Mar 11, 2019 at 12:21 PM Soft Works <softworkz@hotmail.com> wrote:

> > From: Nicolas George
> >
> > Yufei He (12019-03-11):
> > > Matrox M264 is similar to other hardware codecs.
> > >
> > > I saw amf_load_library and nvenc_load_library in ffmpeg.
> >
> > Past practices do not constitute precedents.
> >
> > > We got a lot customers using ffmpeg and they want to use Matrox M264
> to do transcoding.
> >
> > If you make the driver GPL-compatible, there will be no problem at all.
> >
> > Regards,
> >
> > --
> >   Nicolas George
>
> While I don’t care much about Matrox, I’m a bit surprised about the
> recent sounds here. Should  we expect ffmpeg to drop most hw
> accelerations, then?
>
> IANAL, but aren’t drivers clearly considered to be system components?
> In this case they would  be exempted from the GPL afaic?
>

Getting very legal here for someone who's not a lawyer :), but my reading
of the GPL is not that it says "something that acts at system level" (e.g.
hardware), but something that is provided by the base system (i.e. you can
assume it to be installed in some way shape or form regardless of the exact
license that it is accompanied by). For example, you can assume your system
has a libc, even though it might not be a GPL libc.

However, my objection is not legal, it is philosophical. I would prefer
that we (FFmpeg) as a project do not encourage the use of closed-source
software or endorse particular closed-source software (by including support
for it in FFmpeg). We are an open source project, and thus (again: in my
personal opinion) we should only endorse other open source software. That
does not mean closed source software is bad or should not be used. It
merely means we do not endorse it by including support for it.

Ronald
Michael Niedermayer March 11, 2019, 7:48 p.m.
On Mon, Mar 11, 2019 at 01:28:18PM -0400, Ronald S. Bultje wrote:
> Hi,
> 
> On Mon, Mar 11, 2019 at 12:21 PM Soft Works <softworkz@hotmail.com> wrote:
> 
> > > From: Nicolas George
> > >
> > > Yufei He (12019-03-11):
> > > > Matrox M264 is similar to other hardware codecs.
> > > >
> > > > I saw amf_load_library and nvenc_load_library in ffmpeg.
> > >
> > > Past practices do not constitute precedents.
> > >
> > > > We got a lot customers using ffmpeg and they want to use Matrox M264
> > to do transcoding.
> > >
> > > If you make the driver GPL-compatible, there will be no problem at all.
> > >
> > > Regards,
> > >
> > > --
> > >   Nicolas George
> >
> > While I don’t care much about Matrox, I’m a bit surprised about the
> > recent sounds here. Should  we expect ffmpeg to drop most hw
> > accelerations, then?
> >
> > IANAL, but aren’t drivers clearly considered to be system components?
> > In this case they would  be exempted from the GPL afaic?
> >
> 
> Getting very legal here for someone who's not a lawyer :), but my reading
> of the GPL is not that it says "something that acts at system level" (e.g.
> hardware), but something that is provided by the base system (i.e. you can
> assume it to be installed in some way shape or form regardless of the exact
> license that it is accompanied by). For example, you can assume your system
> has a libc, even though it might not be a GPL libc.
> 

> However, my objection is not legal, it is philosophical. 

> I would prefer
> that we (FFmpeg) as a project do not encourage the use of closed-source
> software or endorse particular closed-source software 

I agree


> (by including support
> for it in FFmpeg). We are an open source project, and thus (again: in my
> personal opinion) we should only endorse other open source software. That
> does not mean closed source software is bad or should not be used. It
> merely means we do not endorse it by including support for it.

I disagree that giving users the choice is encouraging a specific choice. Or
That including an option is endorsing it.
I also disagree that closed source software is not bad. It is in my
personal oppinion bad. In fact IMHO its bad for everyone both for the
authors as well as the users.
I agree though that using it if thats what one needs to get something done
is perfectly fine.

And the last useless comment from me today :)
It seems many in these recent threads assume that supporting some interfaces
to non free software harms open source. This sounds logic but iam not so sure
here this is actually true and maybe this is why iam disagreeing a bit.

and btw i do not understand why hw companies are not just making their
software free&open. This might actually increase their hw sales and decrease
their sw maintaince expenses ...

Thanks

[...]

Patch hide | download patch | download mbox

From f19bce56ac931f6329b9493e019e32b79f7bee9c Mon Sep 17 00:00:00 2001
From: yhe <yhe@matrox.com>
Date: Mon, 25 Feb 2019 15:37:05 -0500
Subject: [PATCH] M264 codec support

---
 Changelog               |   1 +
 configure               |   1 +
 doc/general.texi        |   1 +
 fftools/ffmpeg.c        |  14 ++
 libavcodec/Makefile     |   5 +
 libavcodec/allcodecs.c  |   6 +-
 libavcodec/avcodec.h    |   3 +
 libavcodec/codec_desc.c |   9 +
 libavcodec/m264dec.c    | 476 ++++++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/m264dec.h    |  42 +++++
 libavcodec/m264enc.c    | 289 +++++++++++++++++++++++++++++
 libavcodec/m264enc.h    |  39 ++++
 libavcodec/profiles.c   |   5 +
 libavcodec/profiles.h   |   1 +
 14 files changed, 890 insertions(+), 2 deletions(-)
 create mode 100644 libavcodec/m264dec.c
 create mode 100644 libavcodec/m264dec.h
 create mode 100644 libavcodec/m264enc.c
 create mode 100644 libavcodec/m264enc.h

diff --git a/Changelog b/Changelog
index c90f119..f70368b 100644
--- a/Changelog
+++ b/Changelog
@@ -11,6 +11,7 @@  version <next>:
 - dhav demuxer
 - PCM-DVD encoder
 - GIF parser
+- M264 encoder
 
 
 version 4.1:
diff --git a/configure b/configure
index b062b63..161beee 100755
--- a/configure
+++ b/configure
@@ -2618,6 +2618,7 @@  dds_decoder_select="texturedsp"
 dirac_decoder_select="dirac_parse dwt golomb videodsp mpegvideoenc"
 dnxhd_decoder_select="blockdsp idctdsp"
 dnxhd_encoder_select="blockdsp fdctdsp idctdsp mpegvideoenc pixblockdsp"
+#m264_encoder_select="blockdsp fdctdsp idctdsp mpegvideoenc pixblockdsp"
 dolby_e_decoder_select="mdct"
 dvvideo_decoder_select="dvprofile idctdsp"
 dvvideo_encoder_select="dvprofile fdctdsp me_cmp pixblockdsp"
diff --git a/doc/general.texi b/doc/general.texi
index 2bc33d1..e012bad 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -828,6 +828,7 @@  following image formats are supported:
 @item Deluxe Paint Animation @tab     @tab  X
 @item DNxHD                  @tab   X @tab  X
     @tab aka SMPTE VC3
+@item M264                   @tab   X @tab  
 @item Duck TrueMotion 1.0   @tab     @tab  X
     @tab fourcc: DUCK
 @item Duck TrueMotion 2.0    @tab     @tab  X
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 6abcc57..b8fa266 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2418,6 +2418,20 @@  static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_
     if (!*got_output || ret < 0)
         return ret;
 
+   if(*got_output)        
+   {
+      if(decoded_frame->width == 0)
+      {
+         av_log(NULL, AV_LOG_DEBUG, "Frame parameters mismatch context %d,%d,%d != %d,%d,%d\n",
+               decoded_frame->width,
+               decoded_frame->height,
+               decoded_frame->format,
+               ist->dec_ctx->width,
+               ist->dec_ctx->height,
+               ist->dec_ctx->pix_fmt);
+      }
+   }
+
     if(ist->top_field_first>=0)
         decoded_frame->top_field_first = ist->top_field_first;
 
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index d53b8ff..32d147f 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -266,6 +266,8 @@  OBJS-$(CONFIG_DIRAC_DECODER)           += diracdec.o dirac.o diracdsp.o diractab
 OBJS-$(CONFIG_DFA_DECODER)             += dfa.o
 OBJS-$(CONFIG_DNXHD_DECODER)           += dnxhddec.o dnxhddata.o
 OBJS-$(CONFIG_DNXHD_ENCODER)           += dnxhdenc.o dnxhddata.o
+OBJS-$(CONFIG_M264_ENCODER)            += m264enc.o
+OBJS-$(CONFIG_M264_DECODER)            += m264dec.o
 OBJS-$(CONFIG_DOLBY_E_DECODER)         += dolby_e.o kbdwin.o
 OBJS-$(CONFIG_DPX_DECODER)             += dpx.o
 OBJS-$(CONFIG_DPX_ENCODER)             += dpxenc.o
@@ -1093,6 +1095,9 @@  OBJS-$(CONFIG_VP9_RAW_REORDER_BSF)        += vp9_raw_reorder_bsf.o
 OBJS-$(CONFIG_VP9_SUPERFRAME_BSF)         += vp9_superframe_bsf.o
 OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF)   += vp9_superframe_split_bsf.o
 
+
+
+
 # thread libraries
 OBJS-$(HAVE_LIBC_MSVCRT)               += file_open.o
 OBJS-$(HAVE_THREADS)                   += pthread.o pthread_slice.o pthread_frame.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index d70646e..e4a6721 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -84,6 +84,8 @@  extern AVCodec ff_dfa_decoder;
 extern AVCodec ff_dirac_decoder;
 extern AVCodec ff_dnxhd_encoder;
 extern AVCodec ff_dnxhd_decoder;
+extern AVCodec ff_m264_encoder;
+extern AVCodec ff_m264_decoder;
 extern AVCodec ff_dpx_encoder;
 extern AVCodec ff_dpx_decoder;
 extern AVCodec ff_dsicinvideo_decoder;
@@ -800,8 +802,8 @@  const AVCodec *av_codec_iterate(void **opaque)
     ff_thread_once(&av_codec_static_init, av_codec_init_static);
 
     if (c)
-        *opaque = (void*)(i + 1);
-
+      *opaque = (void*)(i + 1);
+      
     return c;
 }
 
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 3922e89..a1c6245 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -452,6 +452,7 @@  enum AVCodecID {
     AV_CODEC_ID_MWSC,
     AV_CODEC_ID_WCMV,
     AV_CODEC_ID_RASC,
+    AV_CODEC_ID_M264,
 
     /* various PCM "codecs" */
     AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
@@ -2978,6 +2979,8 @@  typedef struct AVCodecContext {
 #define FF_PROFILE_PRORES_4444      4
 #define FF_PROFILE_PRORES_XQ        5
 
+#define FF_PROFILE_M264             0
+
     /**
      * level
      * - encoding: Set by user.
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 4850e4f..53859cd 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1691,6 +1691,15 @@  static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("RemotelyAnywhere Screen Capture"),
         .props     = AV_CODEC_PROP_LOSSY,
     },
+    
+    {
+        .id        = AV_CODEC_ID_H264,
+        .type      = AVMEDIA_TYPE_VIDEO,
+        .name      = "m264",
+        .long_name = NULL_IF_CONFIG_SMALL("Matrox M264 Codec"),
+        .props     = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER,
+        .profiles  = NULL_IF_CONFIG_SMALL(ff_h264_profiles),
+    },
 
     /* various PCM "codecs" */
     {
diff --git a/libavcodec/m264dec.c b/libavcodec/m264dec.c
new file mode 100644
index 0000000..e1547e8
--- /dev/null
+++ b/libavcodec/m264dec.c
@@ -0,0 +1,476 @@ 
+/*
+ * M264 H.264 video decoder
+ * Copyright (C) 2019 Matrox
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Matrox M264 card supports h.264 encoding and decoding.
+ */
+
+#include "decode.h"
+#include "cabac.h"
+#include "error_resilience.h"
+#include "h264_parse.h"
+#include "h264_ps.h"
+#include "h264_sei.h"
+#include "h2645_parse.h"
+#include "h264chroma.h"
+#include "h264dsp.h"
+#include "h264pred.h"
+#include "h264qpel.h"
+#include "internal.h"
+#include "mpegutils.h"
+#include "parser.h"
+#include "qpeldsp.h"
+#include "rectangle.h"
+#include "videodsp.h"
+
+#include "config.h"
+#include "libswscale/swscale.h"
+
+#include "m264dec.h"
+
+#ifdef _WIN32
+#include "compat/w32dlfcn.h"
+#else
+#include <dlfcn.h>
+#endif
+
+typedef struct
+{
+   uint16_t width;
+   uint16_t height;
+   uint16_t  scale;
+   uint16_t  rate;
+   uint16_t gopsize;
+   uint32_t bitrate;
+   uint8_t  field_order;
+} M264DecoderInfo;
+
+typedef struct
+{
+   int (*init_m264_decoder)(void *decoder_info, void **m264_decoder_object);
+   int (*exit_m264_decoder)(void *m264_decoder_object);
+   int (*send_packet)(void *m264_decoder_object, void *extradata, unsigned long extradata_size, void *buffer, unsigned long buffer_size);
+   int (*receive_frame)(void *m264_decoder_object, void **buffer_context, void **buffer, unsigned long *buffer_size);
+   int (*release_frame_buffer)(void *m264_decoder_object, void *buffer_context);
+   void *lib_handle;
+   void *decoder_context;
+   int64_t frames;
+   int eof;
+   char *sps_pps;
+   int length_sps_pps;
+} M264Decoder;
+
+void convert_to_annexb(unsigned char * dest, unsigned long data_size)
+{
+   unsigned char *current = dest;
+   union 
+   {
+      unsigned char by4[4];
+      uint32_t length;
+   } union_u32_byte;
+  
+   while ((dest + data_size) > (current + 4))
+   {
+      if((current[0] == 0) &&
+         (current[1] == 0) &&
+         (current[2] == 0) &&
+         (current[3] == 1))
+      {
+         // in case it is already in annex B
+         break;
+      }
+
+      union_u32_byte.by4[3] = current[0];
+      union_u32_byte.by4[2] = current[1];
+      union_u32_byte.by4[1] = current[2];
+      union_u32_byte.by4[0] = current[3];
+
+      current[0] = 0;
+      current[1] = 0;
+      current[2] = 0;
+      current[3] = 1;
+
+      if( union_u32_byte.length <= (data_size - 4 ) )
+         current += (union_u32_byte.length + 4);
+      else
+         break;
+   }
+}
+
+unsigned short convert_bytes_to_ushort(unsigned char * bytes, unsigned char ** bytes_next)
+{
+   union 
+   {
+      unsigned char by2[2];
+      unsigned short ushort;
+   } union_short_byte;
+   
+   union_short_byte.by2[1] = bytes[0];
+   union_short_byte.by2[0] = bytes[1];
+
+   if (bytes_next)
+      *bytes_next = bytes + 2;
+
+   return union_short_byte.ushort;
+};
+
+
+int ff_m264_init_spspps_mp4(AVCodecContext *avctx)
+{
+   M264Decoder *m264_decoder = (M264Decoder *)avctx->priv_data;
+   unsigned char configuration_version;
+   unsigned char avc_profile_indication;
+   unsigned char profile_compatibility;
+   unsigned char avc_level_indication;
+
+   unsigned char size_field_in_bytes;
+
+   unsigned char sps_count = 0;
+
+   unsigned short * array_sps_length = NULL;
+   unsigned char ** array_sps_nal_unit = NULL;
+
+   unsigned char pps_count = 0;
+   unsigned short * array_pps_length = NULL;
+   unsigned char ** array_pps_nal_unit = NULL;
+
+   unsigned char * current;
+
+   unsigned long totalsize = 0;
+
+   current = avctx->extradata;
+   configuration_version = *current++;
+   
+   av_log(avctx, AV_LOG_DEBUG, "ff_m264_init_spspps_mp4: configuration_version = %d\n", configuration_version);
+   assert(configuration_version == 1);
+
+   avc_profile_indication = *current++;
+   av_log(avctx, AV_LOG_DEBUG, "ff_m264_init_spspps_mp4: avc_profile_indication = %d\n", avc_profile_indication);
+
+   profile_compatibility = *current++;
+   av_log(avctx, AV_LOG_DEBUG, "ff_m264_init_spspps_mp4: profile_compatibility = %d\n", profile_compatibility);
+
+   avc_level_indication = *current++;
+   av_log(avctx, AV_LOG_DEBUG, "ff_m264_init_spspps_mp4: avc_level_indication = %d\n", avc_level_indication);
+
+   size_field_in_bytes = *current++;
+
+   assert((size_field_in_bytes & 0xFC) == 0xFC);
+
+   size_field_in_bytes &= 0x03;
+
+   size_field_in_bytes += 1;
+
+   sps_count = *current++;
+
+   sps_count &= 0x1F;
+
+   if (sps_count == 0)
+   {
+      // no valid sps pps
+      return 0;
+   }
+
+   array_sps_length = (unsigned short*) malloc(sps_count * sizeof (unsigned short));
+   array_sps_nal_unit = (unsigned char**) malloc(sps_count * sizeof (unsigned char *));
+
+   for (unsigned long i=0; i< sps_count; i++) 
+   {
+      array_sps_length[i] = convert_bytes_to_ushort(current, &current);
+      array_sps_nal_unit[i] = (unsigned char*)malloc(array_sps_length[i]);
+      memcpy(array_sps_nal_unit[i], current, array_sps_length[i]);
+      current += array_sps_length[i];
+
+      totalsize += 4 + array_sps_length[i];
+   }
+
+   pps_count = *current++;
+
+   array_pps_length = (unsigned short*)malloc(pps_count * sizeof (unsigned short));
+   array_pps_nal_unit = (unsigned char**) malloc(pps_count * sizeof (unsigned char *));
+
+   for (unsigned long i=0; i< pps_count; i++) 
+   {
+      array_pps_length[i] = convert_bytes_to_ushort(current, &current);
+      array_pps_nal_unit[i] = (unsigned char*)malloc(array_pps_length[i]);
+      memcpy(array_pps_nal_unit[i], current, array_pps_length[i]);
+      current += array_pps_length[i];
+      totalsize += 4 + array_pps_length[i];
+   }
+
+   m264_decoder->sps_pps = av_mallocz(totalsize);
+   current = m264_decoder->sps_pps;
+
+   current[0] = 0;
+   current[1] = 0;
+   current[2] = 0;
+   current[3] = 1;
+   current += 4;
+
+   memcpy(current, array_sps_nal_unit[0], array_sps_length[0]);
+   current +=  array_sps_length[0];
+
+   current[0] = 0;
+   current[1] = 0;
+   current[2] = 0;
+   current[3] = 1;
+
+   current += 4;
+
+   memcpy(current, array_pps_nal_unit[0], array_pps_length[0]);
+   current +=  array_pps_length[0];
+
+   m264_decoder->length_sps_pps = totalsize;
+
+   return 0;
+}
+
+av_cold int ff_m264_decode_init(AVCodecContext *avctx)
+{
+   int result = 0;
+   void *lib_handle;
+   M264Decoder *m264_decoder;
+   M264DecoderInfo decoder_info;
+
+   #ifdef _WIN32
+   av_log(avctx, AV_LOG_DEBUG, "_WIN32\n");
+   #elif defined _WIN64
+   av_log(avctx, AV_LOG_DEBUG, "_WIN64\n");
+   #else
+   av_log(avctx, AV_LOG_DEBUG, "linux\n");
+   #endif
+
+#ifdef _WIN32
+   lib_handle = dlopen("mvM264Ffmpeg.dll", RTLD_LAZY);
+#else   
+   lib_handle = dlopen("libmvM264Ffmpeg.so", RTLD_LAZY);
+#endif
+
+   if (!lib_handle)
+   {
+      av_log(avctx, AV_LOG_ERROR, "failed to load mvM264ffmpeg\n");
+   }
+
+   m264_decoder =  av_mallocz(sizeof(M264Decoder));
+
+   m264_decoder->init_m264_decoder = dlsym(lib_handle, "m264_ffmpeg_decoder_init");
+   m264_decoder->exit_m264_decoder = dlsym(lib_handle, "m264_ffmpeg_decoder_exit");
+   m264_decoder->send_packet = dlsym(lib_handle, "m264_ffmpeg_decoder_send_packet");
+   m264_decoder->receive_frame = dlsym(lib_handle, "m264_ffmpeg_decoder_receive_frame");
+   m264_decoder->release_frame_buffer = dlsym(lib_handle, "m264_ffmpeg_decoder_release_frame_buffer");
+   m264_decoder->lib_handle = lib_handle;
+
+   m264_decoder->eof = 0;
+
+   decoder_info.width = avctx->width;
+   decoder_info.height = avctx->height;
+   decoder_info.scale = avctx->framerate.num;
+   decoder_info.rate = avctx->framerate.den;
+
+   switch (avctx->field_order)
+   {
+      case AV_FIELD_UNKNOWN: 
+         av_log(avctx, AV_LOG_DEBUG, "m264_decode_init_h264: avctx->field_order is AV_FIELD_UNKNOWN \n");
+         break;
+      case AV_FIELD_PROGRESSIVE: 
+         av_log(avctx, AV_LOG_DEBUG, "m264_decode_init_h264: avctx->field_order is AV_FIELD_PROGRESSIVE \n");
+         break;
+      case AV_FIELD_TT: 
+         av_log(avctx, AV_LOG_DEBUG, "m264_decode_init_h264: avctx->field_order is AV_FIELD_TT \n");
+         break;
+      case AV_FIELD_BB: 
+         av_log(avctx, AV_LOG_DEBUG, "m264_decode_init_h264: avctx->field_order is AV_FIELD_BB \n");
+         break;
+      case AV_FIELD_TB: 
+         av_log(avctx, AV_LOG_DEBUG, "m264_decode_init_h264: avctx->field_order is AV_FIELD_TB \n");
+         break;
+      case AV_FIELD_BT: 
+         av_log(avctx, AV_LOG_DEBUG, "m264_decode_init_h264: avctx->field_order is AV_FIELD_BT \n");
+         break;
+      default:
+         av_log(avctx, AV_LOG_DEBUG, "m264_decode_init_h264: avctx->field_order is default \n");
+         assert(false);
+         break;
+   }
+
+   decoder_info.field_order = (uint8_t)avctx->field_order;
+
+   av_log(avctx, AV_LOG_DEBUG, "m264_decode_init_h264: avctx->width = %d\n", avctx->width);
+   av_log(avctx, AV_LOG_DEBUG, "m264_decode_init_h264: avctx->height = %d\n", avctx->height);
+   av_log(avctx, AV_LOG_DEBUG, "m264_decode_init_h264: avctx->framerate.num = %d\n", avctx->framerate.num);
+   av_log(avctx, AV_LOG_DEBUG, "m264_decode_init_h264: avctx->framerate.den = %d\n", avctx->framerate.den);
+
+   result = m264_decoder->init_m264_decoder(&decoder_info, &(m264_decoder->decoder_context));
+
+   avctx->priv_data = m264_decoder;
+
+   avctx->pix_fmt = AV_PIX_FMT_YUYV422;
+
+   avctx->bits_per_raw_sample = 8;     
+
+   if (avctx->extradata_size > 0 && avctx->extradata)
+   {
+      ff_m264_init_spspps_mp4(avctx);
+   }
+
+   return result;
+}
+
+int ff_m264_receive_frame(AVCodecContext *avctx, AVFrame *frame)
+{
+   int ret = 0;
+   AVPacket pkt = {0};
+   void *buffer_context = NULL;
+   void *buffer = NULL;
+   unsigned long buffer_size = 0;
+
+   unsigned long line_size;
+
+   int line;
+
+   int actual_line_size;
+
+   unsigned char *srcmem,*dstmem;
+
+   M264Decoder *m264_decoder = (M264Decoder *)avctx->priv_data;
+
+   ret = m264_decoder->receive_frame( m264_decoder->decoder_context, &buffer_context, &buffer, &buffer_size);
+
+   if (ret == -1)
+   {
+      av_log(avctx, AV_LOG_DEBUG, "ff_m264_receive_frame: m264_decoder->receive_packet get eos, return AVERROR_EOF \n");
+      return AVERROR_EOF;
+   }
+
+   if (buffer_size > 0)
+   {
+      av_packet_unref(&pkt);
+
+      ret = ff_get_buffer(avctx, frame, 0);
+
+      line_size = buffer_size / avctx->height;
+
+      srcmem = (unsigned char *)buffer;
+      dstmem = (unsigned char *)frame->data[0];
+
+      actual_line_size = avctx->width * 2;
+
+      for (line = 0; line < avctx->height; line++)
+      {
+         memcpy(dstmem, srcmem, actual_line_size);
+         dstmem += frame->linesize[0];
+         srcmem += line_size;
+      }
+
+      frame->pts = m264_decoder->frames;
+
+      m264_decoder->frames++;
+
+      av_log(avctx, AV_LOG_DEBUG, "ff_m264_receive_frame: m264_decoder->frames = %d\n", (int)m264_decoder->frames);
+      ret = m264_decoder->release_frame_buffer(m264_decoder->decoder_context, buffer_context);
+   }
+   else
+   {
+      if( m264_decoder->eof != 1 )
+      {
+         ret = ff_decode_get_packet(avctx, &pkt);
+
+         av_log(avctx, AV_LOG_DEBUG, "decoder: ff_m264_receive_frame: ff_decode_get_packet  pkt.size = %d\n", pkt.size);
+
+         if (ret < 0 && ret != AVERROR_EOF) {
+            return ret;
+         }
+      }
+
+      if (ret == AVERROR_EOF )
+      {
+         if( m264_decoder->eof != 1 )
+         {
+            pkt.data = NULL;
+            pkt.size = 0;
+            m264_decoder->eof = 1;
+            ret = m264_decoder->send_packet(m264_decoder->decoder_context, m264_decoder->sps_pps, m264_decoder->length_sps_pps, pkt.data, pkt.size);
+         }
+      }
+      else 
+      {
+         if( m264_decoder->eof != 1 )
+         {
+            av_log(avctx, AV_LOG_DEBUG, "decoder: ff_m264_receive_frame: pkt.side_data_elems = %d\n", pkt.side_data_elems);
+
+            if (pkt.data != NULL)
+            {
+               convert_to_annexb( pkt.data, pkt.size);
+            }   
+
+            if (pkt.flags)
+            {
+               ret = m264_decoder->send_packet(m264_decoder->decoder_context, m264_decoder->sps_pps, m264_decoder->length_sps_pps, pkt.data, pkt.size);
+            }
+            else
+            {
+               ret = m264_decoder->send_packet(m264_decoder->decoder_context, NULL , 0, pkt.data, pkt.size);
+            }
+         }
+      }
+
+      ret = AVERROR(EAGAIN);
+   }
+   return ret;
+}
+
+
+int av_cold ff_m264_decode_close(AVCodecContext *avctx)
+{
+   M264Decoder *m264_decoder = (M264Decoder *)avctx->priv_data;
+
+   av_log(avctx, AV_LOG_DEBUG, "ff_m264_decode_close: 1 \n");
+
+   m264_decoder->exit_m264_decoder(m264_decoder->decoder_context);
+
+   dlclose(m264_decoder->lib_handle);   
+
+   av_free(m264_decoder->sps_pps);
+
+   av_free(m264_decoder);
+
+   avctx->priv_data = NULL;
+
+   av_log(avctx, AV_LOG_DEBUG, "ff_m264_decode_close: 2 \n");
+
+   return 0;
+}
+
+
+AVCodec ff_m264_decoder = {
+    .name           = "m264",
+    .long_name      = NULL_IF_CONFIG_SMALL("Matrox M264 Codec"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_H264,
+    .init           = ff_m264_decode_init,
+    .receive_frame   = ff_m264_receive_frame,
+    .close          = ff_m264_decode_close,
+    .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+    .wrapper_name   = "m264",
+};
+
diff --git a/libavcodec/m264dec.h b/libavcodec/m264dec.h
new file mode 100644
index 0000000..ee832fe
--- /dev/null
+++ b/libavcodec/m264dec.h
@@ -0,0 +1,42 @@ 
+/*
+ * M264 H.264 video decoder
+ * Copyright (C) 2019 Matrox
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Matrox M264 card supports h.264 encoding and decoding.
+ */
+
+#ifndef AVCODEC_M264DEC_H
+#define AVCODEC_M264DEC_H
+
+#include "libavutil/fifo.h"
+
+#include "avcodec.h"
+
+int ff_m264_decode_init(AVCodecContext *avctx);
+int ff_m264_decode_close(AVCodecContext *avctx);
+int ff_m264_receive_frame(AVCodecContext *avctx, AVFrame *frame);
+int ff_m264_init_spspps_mp4(AVCodecContext *avctx);
+unsigned short convert_bytes_to_ushort(unsigned char * bytes, unsigned char ** next_bytes);
+void convert_to_annexb(unsigned char * dest, unsigned long datasize);
+
+#endif //AVCODEC_M264DEC_H
+
diff --git a/libavcodec/m264enc.c b/libavcodec/m264enc.c
new file mode 100644
index 0000000..43a95e2
--- /dev/null
+++ b/libavcodec/m264enc.c
@@ -0,0 +1,289 @@ 
+/*
+ * M264 H.264 video encoder
+ * Copyright (C) 2019 Matrox
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Matrox M264 card supports h.264 encoding and decoding.
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/avstring.h"
+#include "libavutil/channel_layout.h"
+#include "libavutil/opt.h"
+#include "config.h"
+#include "libavutil/avassert.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/hwcontext.h"
+#if CONFIG_D3D11VA
+#include "libavutil/hwcontext_d3d11va.h"
+#endif
+#if CONFIG_DXVA2
+#define COBJMACROS
+#include "libavutil/hwcontext_dxva2.h"
+#endif
+#include "libavutil/mem.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/time.h"
+#include "internal.h"
+
+#if CONFIG_D3D11VA
+#include <d3d11.h>
+#endif
+
+#include "libswscale/swscale.h"
+#include "m264enc.h"
+#include "internal.h"
+
+#ifdef _WIN32
+#include "compat/w32dlfcn.h"
+#else
+#include <dlfcn.h>
+#endif
+
+#include "m264enc.h"
+
+typedef struct
+{
+   uint16_t width;
+   uint16_t height;
+   uint16_t  scale;
+   uint16_t  rate;
+   uint16_t gop_size;
+   uint32_t bitrate;
+} M264EncoderInfo;
+
+typedef struct
+{
+   int (*init_m264)(void *encoder_info, void **m264_encoder_object);
+   int (*exit_m264)(void *m264_encoder_object);
+
+   int (*get_uncompressed_buffer)(void *m264_encoder_object, void **buffer_context, void **buffer, unsigned long *buffer_size);
+   int (*send_frame)(void *m264_encoder_object, void *buffer_context, int polarity);
+   int (*receive_packet)(void *m264_encoder_object, void *buffer_context, void **buffer, unsigned long *buffer_size, int32_t *pts, int32_t *dts, int8_t *key);
+   int (*release_packet_buffer)(void *m264_encoder_object, void *buffer_context);
+   void *lib_handle;
+
+   void *encoder_context;
+   struct SwsContext *sw_context;
+} M264Encoder;
+
+av_cold int ff_m264_encode_init(AVCodecContext *avctx)
+{
+   int result = 0;
+   void *lib_handle;
+   M264Encoder *m264_encoder;
+   M264EncoderInfo encoder_info;
+
+#ifdef _WIN32
+   lib_handle = dlopen("mvM264Ffmpeg.dll", RTLD_LAZY);
+#else   
+   lib_handle = dlopen("libmvM264Ffmpeg.so", RTLD_LAZY);
+#endif
+
+   if (!lib_handle)
+   {
+      av_log(avctx, AV_LOG_ERROR, "failed to load mvM264ffmpeg\n");
+   }
+
+   m264_encoder =  av_mallocz(sizeof(M264Encoder));
+
+   m264_encoder->init_m264 = dlsym(lib_handle, "m264_ffmpeg_encoder_init");
+   m264_encoder->exit_m264 = dlsym(lib_handle, "m264_ffmpeg_encoder_exit");
+   m264_encoder->get_uncompressed_buffer = dlsym(lib_handle, "m264_ffmpeg_encoder_get_uncompressed_buffer");
+   m264_encoder->send_frame = dlsym(lib_handle, "m264_ffmpeg_encoder_send_frame");
+   m264_encoder->receive_packet = dlsym(lib_handle, "m264_ffmpeg_encoder_receive_packet");
+   m264_encoder->release_packet_buffer = dlsym(lib_handle, "m264_ffmpeg_encoder_release_packet_buffer");
+   m264_encoder->lib_handle = lib_handle;
+
+   encoder_info.width = avctx->width;
+   encoder_info.height = avctx->height;
+   encoder_info.rate = avctx->framerate.num;
+   encoder_info.scale = avctx->framerate.den;
+   encoder_info.gop_size = avctx->gop_size;
+   encoder_info.bitrate = avctx->bit_rate;
+
+   printf("m264_encode_init_h264: avctx->width = %d\n", avctx->width);
+   printf("m264_encode_init_h264: avctx->height = %d\n", avctx->height);
+   printf("m264_encode_init_h264: avctx->framerate.num = %d\n", avctx->framerate.num);
+   printf("m264_encode_init_h264: avctx->framerate.den = %d\n", avctx->framerate.den);
+   printf("m264_encode_init_h264: avctx->gop_size = %d\n", avctx->gop_size);
+   printf("m264_encode_init_h264: avctx->bit_rate = %" PRId64 "\n", avctx->bit_rate);
+
+   result = m264_encoder->init_m264(&encoder_info, &(m264_encoder->encoder_context));
+
+   avctx->priv_data = m264_encoder;
+
+   return result;
+}
+
+int ff_m264_send_frame(AVCodecContext *avctx, const AVFrame *frame)
+{
+   int result = 0;
+   enum AVPixelFormat src_pixel_format;
+   enum AVPixelFormat dest_pixel_format;
+   uint8_t *dst[1];
+   int dst_stride[1];
+   void *buffer_context;
+
+   unsigned long buffer_size;
+
+   unsigned long line_size;
+
+   int line;
+
+   int actual_line_size;
+
+   unsigned char *srcmem,*dstmem;
+
+   M264Encoder *m264_encoder = (M264Encoder *)avctx->priv_data;
+
+   if (frame)
+   {
+      src_pixel_format = (enum AVPixelFormat)frame->format;
+      dest_pixel_format = AV_PIX_FMT_YUYV422;
+
+      if (m264_encoder->sw_context == NULL)
+      {
+         m264_encoder->sw_context = sws_getContext(frame->width, frame->height, src_pixel_format, frame->width, frame->height,
+                                    dest_pixel_format, SWS_BILINEAR, NULL, NULL, NULL);
+         if (!m264_encoder->sw_context) {
+            av_log(avctx, AV_LOG_ERROR, "failed to load mvm264ffmpeg.so \n");
+            result = -1;
+            return result;
+         }
+      }
+
+      result = m264_encoder->get_uncompressed_buffer(m264_encoder->encoder_context, &buffer_context, (void **)&dst[0], &buffer_size);
+
+      dst_stride[0] = buffer_size / avctx->height;
+      if ( src_pixel_format != AV_PIX_FMT_YUYV422 )
+      {
+         result = sws_scale(m264_encoder->sw_context, (const uint8_t * const*)frame->data, frame->linesize, 0, frame->height, dst, dst_stride);
+      }
+      else
+      {
+         line_size = buffer_size / avctx->height;
+
+         dstmem = (unsigned char *)dst[0];
+         srcmem = (unsigned char *)frame->data[0];
+
+         actual_line_size = avctx->width * 2;
+
+         for (line = 0; line < avctx->height; line++)
+         {
+            memcpy(dstmem, srcmem, actual_line_size);
+            srcmem += frame->linesize[0];
+            dstmem += line_size;
+         }
+      }
+
+      av_log(avctx, AV_LOG_DEBUG, "ff_m264_send_frame: frame->width = %d, frame->height = %d\n", frame->width, frame->height);
+
+      result = m264_encoder->send_frame(m264_encoder->encoder_context, buffer_context, 0);
+   }
+   else
+   {
+      av_log(avctx, AV_LOG_DEBUG, "ff_m264_send_frame: frame is null. eof\n");
+      result = m264_encoder->send_frame(m264_encoder->encoder_context, NULL, 0);
+   }
+
+   return result;
+}
+
+int ff_m264_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
+{
+   int result;
+   M264Encoder *m264_encoder = (M264Encoder *)avctx->priv_data;
+
+   void *buffer_context = NULL;
+   void *buffer = NULL;
+   unsigned long buffer_size = 0;
+
+   int32_t pts, dts;
+   int8_t key;
+
+   result = m264_encoder->receive_packet(m264_encoder->encoder_context, &buffer_context, &buffer, &buffer_size, &pts, &dts, &key);
+
+   if (result == -1)
+   {
+      av_log(avctx, AV_LOG_DEBUG, "ff_m264_receive_packet: m264_encoder->receive_packet get eos, return AVERROR_EOF\n");
+      return AVERROR_EOF;
+   }
+   else if (buffer_size == 0)
+   {
+      return AVERROR(EAGAIN);
+   }
+
+   av_log(avctx, AV_LOG_DEBUG, "ff_m264_receive_packet  m264_encoder->receive_packet buffer_size = %d\n", (int)buffer_size); 
+
+   result = ff_alloc_packet2(avctx, avpkt, buffer_size, 0);
+
+   av_log(avctx, AV_LOG_DEBUG, "ff_m264_receive_packet  ff_alloc_packet2 result = %d\n", result); 
+   memcpy(avpkt->data, buffer, buffer_size);
+   av_log(avctx, AV_LOG_DEBUG, "ff_m264_receive_packet  memcpy done\n"); 
+
+   avpkt->dts = dts;
+   avpkt->pts = pts + 2;
+   avpkt->flags = key ? AV_PKT_FLAG_KEY : 0;
+
+   av_log(avctx, AV_LOG_DEBUG, "ff_m264_receive_packet  m264_encoder->release_packet_buffer before \n"); 
+   result = m264_encoder->release_packet_buffer(m264_encoder->encoder_context, buffer_context);
+   av_log(avctx, AV_LOG_DEBUG, "ff_m264_receive_packet  m264_encoder->release_packet_buffer after \n"); 
+
+   return result;
+}
+
+int av_cold ff_m264_encode_close(AVCodecContext *avctx)
+{
+   M264Encoder *m264_encoder = (M264Encoder *)avctx->priv_data;
+
+   av_log(avctx, AV_LOG_DEBUG, "ff_m264_encode_close 1");
+   
+   m264_encoder->exit_m264(m264_encoder->encoder_context);
+
+   sws_freeContext(m264_encoder->sw_context);
+
+   dlclose(m264_encoder->lib_handle);   
+
+   av_free(m264_encoder);
+
+   avctx->priv_data = NULL;
+
+   av_log(avctx, AV_LOG_DEBUG, "ff_m264_encode_close 2");
+
+   return 0;
+}
+
+AVCodec ff_m264_encoder = {
+    .name           = "m264",
+    .long_name      = NULL_IF_CONFIG_SMALL("Matrox M264 Codec"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_H264,
+    .init           = ff_m264_encode_init,
+    .send_frame     = ff_m264_send_frame,
+    .receive_packet = ff_m264_receive_packet,
+    .close          = ff_m264_encode_close,
+    .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+    .wrapper_name   = "m264",
+};
+
+
diff --git a/libavcodec/m264enc.h b/libavcodec/m264enc.h
new file mode 100644
index 0000000..63718e6
--- /dev/null
+++ b/libavcodec/m264enc.h
@@ -0,0 +1,39 @@ 
+/*
+ * M264 H.264 video encoder
+ * Copyright (C) 2019 Matrox
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Matrox M264 card supports h.264 encoding and decoding.
+ */
+
+#ifndef AVCODEC_M264ENC_H
+#define AVCODEC_M264ENC_H
+
+#include "libavutil/fifo.h"
+
+#include "avcodec.h"
+
+int ff_m264_encode_init(AVCodecContext *avctx);
+int ff_m264_encode_close(AVCodecContext *avctx);
+int ff_m264_send_frame(AVCodecContext *avctx, const AVFrame *frame);
+int ff_m264_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
+
+#endif //AVCODEC_AMAVCODEC_M264ENC_H
diff --git a/libavcodec/profiles.c b/libavcodec/profiles.c
index e6f937f..1c161f9 100644
--- a/libavcodec/profiles.c
+++ b/libavcodec/profiles.c
@@ -170,4 +170,9 @@  const AVProfile ff_mjpeg_profiles[] = {
     { FF_PROFILE_UNKNOWN }
 };
 
+const AVProfile ff_m264_profiles[] = {
+  { FF_PROFILE_M264,       "M264"},
+};
+
+
 #endif /* !CONFIG_SMALL */
diff --git a/libavcodec/profiles.h b/libavcodec/profiles.h
index ab61e03..9eafda2 100644
--- a/libavcodec/profiles.h
+++ b/libavcodec/profiles.h
@@ -35,5 +35,6 @@  extern const AVProfile ff_av1_profiles[];
 extern const AVProfile ff_sbc_profiles[];
 extern const AVProfile ff_prores_profiles[];
 extern const AVProfile ff_mjpeg_profiles[];
+extern const AVProfile ff_m264_profiles[];
 
 #endif /* AVCODEC_PROFILES_H */
-- 
2.7.4