summaryrefslogtreecommitdiff
path: root/vhook/watermark.c
diff options
context:
space:
mode:
authorDiego Biurrun <diego@biurrun.de>2009-03-03 14:09:10 +0000
committerDiego Biurrun <diego@biurrun.de>2009-03-03 14:09:10 +0000
commitfdf119062e21547fbd9c3bb465cf6b2a276359ae (patch)
tree4e89853c43850d8cb6812987b9ce17b5eac0a9d8 /vhook/watermark.c
parentf989d397529cc86c25dfd8992e865ddd76ecf1dd (diff)
Remove deprecated vhook subsystem.
Originally committed as revision 17769 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'vhook/watermark.c')
-rw-r--r--vhook/watermark.c655
1 files changed, 0 insertions, 655 deletions
diff --git a/vhook/watermark.c b/vhook/watermark.c
deleted file mode 100644
index 1d4be28f6c..0000000000
--- a/vhook/watermark.c
+++ /dev/null
@@ -1,655 +0,0 @@
-/*
- * Watermark Hook
- * Copyright (c) 2005 Marcus Engene myfirstname(at)mylastname.se
- *
- * parameters for watermark:
- * -m nbr = nbr is 0..1. 0 is the default mode, see below.
- * -t nbr = nbr is six digit hex. Threshold.
- * -f file = file is the watermark image filename. You must specify this!
- *
- * MODE 0:
- * The watermark picture works like this (assuming color intensities 0..0xff):
- * Per color do this:
- * If mask color is 0x80, no change to the original frame.
- * If mask color is < 0x80 the abs difference is subtracted from the frame. If
- * result < 0, result = 0
- * If mask color is > 0x80 the abs difference is added to the frame. If result
- * > 0xff, result = 0xff
- *
- * You can override the 0x80 level with the -t flag. E.g. if threshold is
- * 000000 the color value of watermark is added to the destination.
- *
- * This way a mask that is visible both in light pictures and in dark can be
- * made (fex by using a picture generated by Gimp and the bump map tool).
- *
- * An example watermark file is at
- * http://engene.se/ffmpeg_watermark.gif
- *
- * MODE 1:
- * Per color do this:
- * If mask color > threshold color then the watermark pixel is used.
- *
- * Example usage:
- * ffmpeg -i infile -vhook '/path/watermark.so -f wm.gif' -an out.mov
- * ffmpeg -i infile -vhook '/path/watermark.so -f wm.gif -m 1 -t 222222' -an out.mov
- *
- * Note that the entire vhook argument is encapsulated in ''. This
- * way, arguments to the vhook won't be mixed up with those for ffmpeg.
- *
- * 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
- */
-
-#include <stdlib.h>
-//#include <fcntl.h>
-#include <unistd.h>
-#include <stdarg.h>
-
-#include "libavutil/common.h"
-#include "libavformat/avformat.h"
-#include "libavformat/framehook.h"
-#include "libswscale/swscale.h"
-
-static int sws_flags = SWS_BICUBIC;
-
-typedef struct {
- char filename[2000];
- int x_size;
- int y_size;
-
- /* get_watermark_picture() variables */
- AVFormatContext *pFormatCtx;
- const char *p_ext;
- int videoStream;
- int frameFinished;
- AVCodecContext *pCodecCtx;
- AVCodec *pCodec;
- AVFrame *pFrame;
- AVPacket packet;
- int numBytes;
- uint8_t *buffer;
- int i;
- AVInputFormat *file_iformat;
- AVStream *st;
- int is_done;
- AVFrame *pFrameRGB;
- int thrR;
- int thrG;
- int thrB;
- int mode;
-
- // This vhook first converts frame to RGB ...
- struct SwsContext *toRGB_convert_ctx;
- // ... then converts a watermark and applies it to the RGB frame ...
- struct SwsContext *watermark_convert_ctx;
- // ... and finally converts back frame from RGB to initial format
- struct SwsContext *fromRGB_convert_ctx;
-} ContextInfo;
-
-int get_watermark_picture(ContextInfo *ci, int cleanup);
-
-
-/****************************************************************************
- *
- ****************************************************************************/
-void Release(void *ctx)
-{
- ContextInfo *ci;
- ci = (ContextInfo *) ctx;
-
- if (ci) {
- get_watermark_picture(ci, 1);
- sws_freeContext(ci->toRGB_convert_ctx);
- sws_freeContext(ci->watermark_convert_ctx);
- sws_freeContext(ci->fromRGB_convert_ctx);
- }
- av_free(ctx);
-}
-
-
-/****************************************************************************
- *
- ****************************************************************************/
-int Configure(void **ctxp, int argc, char *argv[])
-{
- ContextInfo *ci;
- int c;
- int tmp = 0;
-
- if (0 == (*ctxp = av_mallocz(sizeof(ContextInfo)))) return -1;
- ci = (ContextInfo *) *ctxp;
-
- optind = 1;
-
- // Struct is mallocz:ed so no need to reset.
- ci->thrR = 0x80;
- ci->thrG = 0x80;
- ci->thrB = 0x80;
-
- while ((c = getopt(argc, argv, "f:m:t:")) > 0) {
- switch (c) {
- case 'f':
- strncpy(ci->filename, optarg, 1999);
- ci->filename[1999] = 0;
- break;
- case 'm':
- ci->mode = atoi(optarg);
- break;
- case 't':
- if (1 != sscanf(optarg, "%x", &tmp)) {
- av_log(NULL, AV_LOG_ERROR, "Watermark: argument to -t must be a 6 digit hex number\n");
- return -1;
- }
- ci->thrR = (tmp >> 16) & 0xff;
- ci->thrG = (tmp >> 8) & 0xff;
- ci->thrB = (tmp >> 0) & 0xff;
- break;
- default:
- av_log(NULL, AV_LOG_ERROR, "Watermark: Unrecognized argument '%s'\n", argv[optind]);
- return -1;
- }
- }
-
- //
- if (0 == ci->filename[0]) {
- av_log(NULL, AV_LOG_ERROR, "Watermark: There is no filename specified.\n");
- return -1;
- }
-
- av_register_all();
- return get_watermark_picture(ci, 0);
-}
-
-
-/****************************************************************************
- * For mode 0 (the original one)
- ****************************************************************************/
-static void Process0(void *ctx,
- AVPicture *picture,
- enum PixelFormat pix_fmt,
- int src_width,
- int src_height,
- int64_t pts)
-{
- ContextInfo *ci = (ContextInfo *) ctx;
- char *buf = 0;
- AVPicture picture1;
- AVPicture *pict = picture;
-
- AVFrame *pFrameRGB;
- int xm_size;
- int ym_size;
-
- int x;
- int y;
- int offs, offsm;
- int mpoffs;
- uint32_t *p_pixel = 0;
- uint32_t pixel_meck;
- uint32_t pixel;
- uint32_t pixelm;
- int tmp;
- int thrR = ci->thrR;
- int thrG = ci->thrG;
- int thrB = ci->thrB;
-
- if (pix_fmt != PIX_FMT_RGB32) {
- int size;
-
- size = avpicture_get_size(PIX_FMT_RGB32, src_width, src_height);
- buf = av_malloc(size);
-
- avpicture_fill(&picture1, buf, PIX_FMT_RGB32, src_width, src_height);
-
- // if we already got a SWS context, let's realloc if is not re-useable
- ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx,
- src_width, src_height, pix_fmt,
- src_width, src_height, PIX_FMT_RGB32,
- sws_flags, NULL, NULL, NULL);
- if (ci->toRGB_convert_ctx == NULL) {
- av_log(NULL, AV_LOG_ERROR,
- "Cannot initialize the toRGB conversion context\n");
- return;
- }
-
-// img_convert parameters are 2 first destination, then 4 source
-// sws_scale parameters are context, 4 first source, then 2 destination
- sws_scale(ci->toRGB_convert_ctx,
- picture->data, picture->linesize, 0, src_height,
- picture1.data, picture1.linesize);
-
- pict = &picture1;
- }
-
- /* Insert filter code here */ /* ok */
-
- // Get me next frame
- if (0 > get_watermark_picture(ci, 0)) {
- return;
- }
- // These are the three original static variables in the ffmpeg hack.
- pFrameRGB = ci->pFrameRGB;
- xm_size = ci->x_size;
- ym_size = ci->y_size;
-
- // I'll do the *4 => <<2 crap later. Most compilers understand that anyway.
- // According to avcodec.h PIX_FMT_RGB32 is handled in endian specific manner.
- for (y=0; y<src_height; y++) {
- offs = y * (src_width * 4);
- offsm = (((y * ym_size) / src_height) * 4) * xm_size; // offsm first in maskline. byteoffs!
- for (x=0; x<src_width; x++) {
- mpoffs = offsm + (((x * xm_size) / src_width) * 4);
- p_pixel = (uint32_t *)&((pFrameRGB->data[0])[mpoffs]);
- pixelm = *p_pixel;
- p_pixel = (uint32_t *)&((pict->data[0])[offs]);
- pixel = *p_pixel;
-// pixelm = *((uint32_t *)&(pFrameRGB->data[mpoffs]));
- pixel_meck = pixel & 0xff000000;
-
- // R
- tmp = (int)((pixel >> 16) & 0xff) + (int)((pixelm >> 16) & 0xff) - thrR;
- if (tmp > 255) tmp = 255;
- if (tmp < 0) tmp = 0;
- pixel_meck |= (tmp << 16) & 0xff0000;
- // G
- tmp = (int)((pixel >> 8) & 0xff) + (int)((pixelm >> 8) & 0xff) - thrG;
- if (tmp > 255) tmp = 255;
- if (tmp < 0) tmp = 0;
- pixel_meck |= (tmp << 8) & 0xff00;
- // B
- tmp = (int)((pixel >> 0) & 0xff) + (int)((pixelm >> 0) & 0xff) - thrB;
- if (tmp > 255) tmp = 255;
- if (tmp < 0) tmp = 0;
- pixel_meck |= (tmp << 0) & 0xff;
-
-
- // test:
- //pixel_meck = pixel & 0xff000000;
- //pixel_meck |= (pixelm & 0x00ffffff);
-
- *p_pixel = pixel_meck;
-
- offs += 4;
- } // foreach X
- } // foreach Y
-
-
-
-
- if (pix_fmt != PIX_FMT_RGB32) {
- ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx,
- src_width, src_height, PIX_FMT_RGB32,
- src_width, src_height, pix_fmt,
- sws_flags, NULL, NULL, NULL);
- if (ci->fromRGB_convert_ctx == NULL) {
- av_log(NULL, AV_LOG_ERROR,
- "Cannot initialize the fromRGB conversion context\n");
- return;
- }
-// img_convert parameters are 2 first destination, then 4 source
-// sws_scale parameters are context, 4 first source, then 2 destination
- sws_scale(ci->fromRGB_convert_ctx,
- picture1.data, picture1.linesize, 0, src_height,
- picture->data, picture->linesize);
- }
-
- av_free(buf);
-}
-
-
-/****************************************************************************
- * For mode 1 (the original one)
- ****************************************************************************/
-static void Process1(void *ctx,
- AVPicture *picture,
- enum PixelFormat pix_fmt,
- int src_width,
- int src_height,
- int64_t pts)
-{
- ContextInfo *ci = (ContextInfo *) ctx;
- char *buf = 0;
- AVPicture picture1;
- AVPicture *pict = picture;
-
- AVFrame *pFrameRGB;
- int xm_size;
- int ym_size;
-
- int x;
- int y;
- int offs, offsm;
- int mpoffs;
- uint32_t *p_pixel = 0;
- uint32_t pixel;
- uint32_t pixelm;
-
- if (pix_fmt != PIX_FMT_RGB32) {
- int size;
-
- size = avpicture_get_size(PIX_FMT_RGB32, src_width, src_height);
- buf = av_malloc(size);
-
- avpicture_fill(&picture1, buf, PIX_FMT_RGB32, src_width, src_height);
-
- // if we already got a SWS context, let's realloc if is not re-useable
- ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx,
- src_width, src_height, pix_fmt,
- src_width, src_height, PIX_FMT_RGB32,
- sws_flags, NULL, NULL, NULL);
- if (ci->toRGB_convert_ctx == NULL) {
- av_log(NULL, AV_LOG_ERROR,
- "Cannot initialize the toRGB conversion context\n");
- return;
- }
-
-// img_convert parameters are 2 first destination, then 4 source
-// sws_scale parameters are context, 4 first source, then 2 destination
- sws_scale(ci->toRGB_convert_ctx,
- picture->data, picture->linesize, 0, src_height,
- picture1.data, picture1.linesize);
-
- pict = &picture1;
- }
-
- /* Insert filter code here */ /* ok */
-
- // Get me next frame
- if (0 > get_watermark_picture(ci, 0)) {
- return;
- }
- // These are the three original static variables in the ffmpeg hack.
- pFrameRGB = ci->pFrameRGB;
- xm_size = ci->x_size;
- ym_size = ci->y_size;
-
- // I'll do the *4 => <<2 crap later. Most compilers understand that anyway.
- // According to avcodec.h PIX_FMT_RGB32 is handled in endian specific manner.
- for (y=0; y<src_height; y++) {
- offs = y * (src_width * 4);
- offsm = (((y * ym_size) / src_height) * 4) * xm_size; // offsm first in maskline. byteoffs!
- for (x=0; x<src_width; x++) {
- mpoffs = offsm + (((x * xm_size) / src_width) * 4);
- p_pixel = (uint32_t *)&((pFrameRGB->data[0])[mpoffs]);
- pixelm = *p_pixel; /* watermark pixel */
- p_pixel = (uint32_t *)&((pict->data[0])[offs]);
- pixel = *p_pixel;
-
- if (((pixelm >> 16) & 0xff) > ci->thrR ||
- ((pixelm >> 8) & 0xff) > ci->thrG ||
- ((pixelm >> 0) & 0xff) > ci->thrB)
- {
- *p_pixel = pixelm;
- } else {
- *p_pixel = pixel;
- }
- offs += 4;
- } // foreach X
- } // foreach Y
-
- if (pix_fmt != PIX_FMT_RGB32) {
- ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx,
- src_width, src_height, PIX_FMT_RGB32,
- src_width, src_height, pix_fmt,
- sws_flags, NULL, NULL, NULL);
- if (ci->fromRGB_convert_ctx == NULL) {
- av_log(NULL, AV_LOG_ERROR,
- "Cannot initialize the fromRGB conversion context\n");
- return;
- }
-// img_convert parameters are 2 first destination, then 4 source
-// sws_scale parameters are context, 4 first source, then 2 destination
- sws_scale(ci->fromRGB_convert_ctx,
- picture1.data, picture1.linesize, 0, src_height,
- picture->data, picture->linesize);
- }
-
- av_free(buf);
-}
-
-
-/****************************************************************************
- * This is the function ffmpeg.c callbacks.
- ****************************************************************************/
-void Process(void *ctx,
- AVPicture *picture,
- enum PixelFormat pix_fmt,
- int src_width,
- int src_height,
- int64_t pts)
-{
- ContextInfo *ci = (ContextInfo *) ctx;
- if (1 == ci->mode) {
- Process1(ctx, picture, pix_fmt, src_width, src_height, pts);
- } else {
- Process0(ctx, picture, pix_fmt, src_width, src_height, pts);
- }
-}
-
-
-/****************************************************************************
- * When cleanup == 0, we try to get the next frame. If no next frame, nothing
- * is done.
- *
- * This code follows the example on
- * http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html
- *
- * 0 = ok, -1 = error
- ****************************************************************************/
-int get_watermark_picture(ContextInfo *ci, int cleanup)
-{
- if (1 == ci->is_done && 0 == cleanup) return 0;
-
- // Yes, *pFrameRGB arguments must be null the first time otherwise it's not good..
- // This block is only executed the first time we enter this function.
- if (0 == ci->pFrameRGB &&
- 0 == cleanup)
- {
-
- /*
- * The last three parameters specify the file format, buffer size and format
- * parameters; by simply specifying NULL or 0 we ask libavformat to auto-detect
- * the format and use a default buffer size. (Didn't work!)
- */
- if (av_open_input_file(&ci->pFormatCtx, ci->filename, NULL, 0, NULL) != 0) {
-
- // Martin says this should not be necessary but it failed for me sending in
- // NULL instead of file_iformat to av_open_input_file()
- ci->i = strlen(ci->filename);
- if (0 == ci->i) {
- av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() No filename to watermark vhook\n");
- return -1;
- }
- while (ci->i > 0) {
- if (ci->filename[ci->i] == '.') {
- ci->i++;
- break;
- }
- ci->i--;
- }
- ci->p_ext = &(ci->filename[ci->i]);
- ci->file_iformat = av_find_input_format (ci->p_ext);
- if (0 == ci->file_iformat) {
- av_log(NULL, AV_LOG_INFO, "get_watermark_picture() attempt to use image2 for [%s]\n", ci->p_ext);
- ci->file_iformat = av_find_input_format ("image2");
- }
- if (0 == ci->file_iformat) {
- av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Really failed to find iformat [%s]\n", ci->p_ext);
- return -1;
- }
- // now continues the Martin template.
-
- if (av_open_input_file(&ci->pFormatCtx, ci->filename, ci->file_iformat, 0, NULL)!=0) {
- av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to open input file [%s]\n", ci->filename);
- return -1;
- }
- }
-
- /*
- * This fills the streams field of the AVFormatContext with valid information.
- */
- if(av_find_stream_info(ci->pFormatCtx)<0) {
- av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find stream info\n");
- return -1;
- }
-
- /*
- * As mentioned in the introduction, we'll handle only video streams, not audio
- * streams. To make things nice and easy, we simply use the first video stream we
- * find.
- */
- ci->videoStream=-1;
- for(ci->i = 0; ci->i < ci->pFormatCtx->nb_streams; ci->i++)
- if(ci->pFormatCtx->streams[ci->i]->codec->codec_type==CODEC_TYPE_VIDEO)
- {
- ci->videoStream = ci->i;
- break;
- }
- if(ci->videoStream == -1) {
- av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find any video stream\n");
- return -1;
- }
-
- ci->st = ci->pFormatCtx->streams[ci->videoStream];
- ci->x_size = ci->st->codec->width;
- ci->y_size = ci->st->codec->height;
-
- // Get a pointer to the codec context for the video stream
- ci->pCodecCtx = ci->pFormatCtx->streams[ci->videoStream]->codec;
-
-
- /*
- * OK, so now we've got a pointer to the so-called codec context for our video
- * stream, but we still have to find the actual codec and open it.
- */
- // Find the decoder for the video stream
- ci->pCodec = avcodec_find_decoder(ci->pCodecCtx->codec_id);
- if(ci->pCodec == NULL) {
- av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find any codec\n");
- return -1;
- }
-
-
- // Open codec
- if(avcodec_open(ci->pCodecCtx, ci->pCodec)<0) {
- av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to open codec\n");
- return -1;
- }
-
- // Hack to correct wrong frame rates that seem to be generated by some
- // codecs
- if (ci->pCodecCtx->time_base.den>1000 && ci->pCodecCtx->time_base.num==1)
- ci->pCodecCtx->time_base.num=1000;
-
- /*
- * Allocate a video frame to store the decoded images in.
- */
- ci->pFrame = avcodec_alloc_frame();
-
-
- /*
- * The RGB image pFrameRGB (of type AVFrame *) is allocated like this:
- */
- // Allocate an AVFrame structure
- ci->pFrameRGB=avcodec_alloc_frame();
- if(ci->pFrameRGB==NULL) {
- av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to alloc pFrameRGB\n");
- return -1;
- }
-
- // Determine required buffer size and allocate buffer
- ci->numBytes = avpicture_get_size(PIX_FMT_RGB32, ci->pCodecCtx->width,
- ci->pCodecCtx->height);
- ci->buffer = av_malloc(ci->numBytes);
-
- // Assign appropriate parts of buffer to image planes in pFrameRGB
- avpicture_fill((AVPicture *)ci->pFrameRGB, ci->buffer, PIX_FMT_RGB32,
- ci->pCodecCtx->width, ci->pCodecCtx->height);
- }
- // TODO loop, pingpong etc?
- if (0 == cleanup)
- {
-// av_log(NULL, AV_LOG_DEBUG, "get_watermark_picture() Get a frame\n");
- while(av_read_frame(ci->pFormatCtx, &ci->packet)>=0)
- {
- // Is this a packet from the video stream?
- if(ci->packet.stream_index == ci->videoStream)
- {
- // Decode video frame
- avcodec_decode_video(ci->pCodecCtx, ci->pFrame, &ci->frameFinished,
- ci->packet.data, ci->packet.size);
-
- // Did we get a video frame?
- if(ci->frameFinished)
- {
- // Convert the image from its native format to RGB32
- ci->watermark_convert_ctx =
- sws_getCachedContext(ci->watermark_convert_ctx,
- ci->pCodecCtx->width, ci->pCodecCtx->height, ci->pCodecCtx->pix_fmt,
- ci->pCodecCtx->width, ci->pCodecCtx->height, PIX_FMT_RGB32,
- sws_flags, NULL, NULL, NULL);
- if (ci->watermark_convert_ctx == NULL) {
- av_log(NULL, AV_LOG_ERROR,
- "Cannot initialize the watermark conversion context\n");
- return -1;
- }
-// img_convert parameters are 2 first destination, then 4 source
-// sws_scale parameters are context, 4 first source, then 2 destination
- sws_scale(ci->watermark_convert_ctx,
- ci->pFrame->data, ci->pFrame->linesize, 0, ci->pCodecCtx->height,
- ci->pFrameRGB->data, ci->pFrameRGB->linesize);
-
- // Process the video frame (save to disk etc.)
- //fprintf(stderr,"banan() New frame!\n");
- //DoSomethingWithTheImage(ci->pFrameRGB);
- return 0;
- }
- }
-
- // Free the packet that was allocated by av_read_frame
- av_free_packet(&ci->packet);
- }
- ci->is_done = 1;
- return 0;
- } // if 0 != cleanup
-
- if (0 != cleanup)
- {
- // Free the RGB image
- av_freep(&ci->buffer);
- av_freep(&ci->pFrameRGB);
-
- // Close the codec
- if (0 != ci->pCodecCtx) {
- avcodec_close(ci->pCodecCtx);
- ci->pCodecCtx = 0;
- }
-
- // Close the video file
- if (0 != ci->pFormatCtx) {
- av_close_input_file(ci->pFormatCtx);
- ci->pFormatCtx = 0;
- }
-
- ci->is_done = 0;
- }
- return 0;
-}
-
-
-void parse_arg_file(const char *filename)
-{
-}