Page 1 of 1

FFmpeg: Handle (apply and undo) patches from an email

Posted: Sun Apr 28, 2013 2:45 pm
by ^rooker
There's information about submitting patches for FFmpeg in the official documentation, but I wanted to apply a patchset sent on the ffmpeg-devel mailing list.

My git-foo ain't too great, and I'm used to using the good old "GNU patch" for applying diff-patches. But it seems that using "git apply" is actually the way to go in this case.

I've read "Git tip of the week: Patches by Email (by Al Blue)" and it seemed to work fine.

This text here will describe the following:
  • how to handle a patch for FFmpeg that came by email (mostly from the FFmpeg mailing lists)
  • how to revert the patched files back to the recent git HEAD (useful for reproducing stuff...)

It might seem trivial for most developers who're working with git everyday, but I tend to forget stuff, so I better write it down :)

Patch from email

Posted: Sun Apr 28, 2013 2:46 pm
by ^rooker
Let's begin:

A) How to handle a patch for FFmpeg that came by email (mostly from the FFmpeg mailing lists)
Here's a real world example: A patch for FFv1 to switch to "ThreadFrame"

The mail looks like this:

Code: Select all

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
---
 libavcodec/ffv1.c    |   12 +++++++++---
 libavcodec/ffv1.h    |    3 ++-
 libavcodec/ffv1dec.c |   29 +++++++++++++++++------------
 libavcodec/ffv1enc.c |   16 ++++++++--------
 4 files changed, 36 insertions(+), 24 deletions(-)

diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 404b0e3..8b3d35b 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -48,8 +48,8 @@ av_cold int ffv1_common_init(AVCodecContext *avctx)
     s->avctx = avctx;
     s->flags = avctx->flags;
 
-    avcodec_get_frame_defaults(&s->picture);
-
+    s->picture.f = avcodec_alloc_frame();
+    s->last_picture.f = av_frame_alloc();
...
...
... 
@@ -1014,7 +1014,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     ff_init_range_encoder(c, pkt->data, pkt->size);
     ff_build_rac_states(c, 0.05 * (1LL << 32), 256 - 8);
 
-    *p           = *pict;
+    av_frame_ref(p, pict);
     p->pict_type = AV_PICTURE_TYPE_I;
 
     if (avctx->gop_size == 0 || f->picture_number % avctx->gop_size == 0) {
-- 1.7.9.5 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel 
(For a complete copy of what the original mail looked like exactly, take a look at the ffmpeg-devel archive)

Now copy the text in the mail from the first line starting with "diff --git ..." down until the "--" at the bottom, like this:

Code: Select all

diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 404b0e3..8b3d35b 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -48,8 +48,8 @@ av_cold int ffv1_common_init(AVCodecContext *avctx)
...
...
...
...
-    *p           = *pict;
+    av_frame_ref(p, pict);
     p->pict_type = AV_PICTURE_TYPE_I;
 
     if (avctx->gop_size == 0 || f->picture_number % avctx->gop_size == 0) {
Copy/paste that block to a textfile and give it a meaningful name. For example, use the description from the email.
In this case I called it:
"patches/ffv1-threadframe.patch"
(I prefer to put patches in a subfolder of ffmpeg's source, called "patches" - but that's just cosmetics)

Now, in the folder where you've checked out the git-HEAD, apply the patch using "git apply":

Code: Select all

$ git apply -v patches/ffv1-threadframe.patch
If everything's fine, you should see a happy report like this:
Checking patch libavcodec/ffv1.c...
Checking patch libavcodec/ffv1.h...
Checking patch libavcodec/ffv1dec.c...
Checking patch libavcodec/ffv1enc.c...
Applied patch libavcodec/ffv1.c cleanly.
Applied patch libavcodec/ffv1.h cleanly.
Applied patch libavcodec/ffv1dec.c cleanly.
Applied patch libavcodec/ffv1enc.c cleanly.

Re: FFmpeg: Handle (apply and undo) patches from an email

Posted: Sun Apr 28, 2013 2:52 pm
by ^rooker
B) how to revert the patched files back to the recent git HEAD (useful for reproducing stuff...)
This is nice for comparing different patches on the same source.

After applying the above patchset, running "git status" shows you which files got touched:

Code: Select all

$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: libavcodec/ffv1.c
# modified: libavcodec/ffv1.h
# modified: libavcodec/ffv1dec.c
# modified: libavcodec/ffv1enc.c
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# patches/
no changes added to commit (use "git add" and/or "git commit -a")
(You also see the "patches" directory, which was manually added)

"git status" is so nice to already tell you what to do, if you want to discard changes in your working directory.
In our case, I'd do it like this:

Code: Select all

$ git checkout -- libavcodec/ffv1*.[ch]
(If everything went fine, that command returns nothing. So don't worry about its silence)

Now your sourcecode should be reset to its previous version (git HEAD in most cases) - ready to receive other patches :)