• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

vhook/watermark.c

Go to the documentation of this file.
00001 /*
00002  * Watermark Hook
00003  * Copyright (c) 2005 Marcus Engene myfirstname(at)mylastname.se
00004  *
00005  * parameters for watermark:
00006  *  -m nbr = nbr is 0..1. 0 is the default mode, see below.
00007  *  -t nbr = nbr is six digit hex. Threshold.
00008  *  -f file = file is the watermark image filename. You must specify this!
00009  *
00010  * MODE 0:
00011  * The watermark picture works like this (assuming color intensities 0..0xff):
00012  * Per color do this:
00013  * If mask color is 0x80, no change to the original frame.
00014  * If mask color is < 0x80 the abs difference is subtracted from the frame. If
00015  * result < 0, result = 0
00016  * If mask color is > 0x80 the abs difference is added to the frame. If result
00017  * > 0xff, result = 0xff
00018  *
00019  * You can override the 0x80 level with the -t flag. E.g. if threshold is
00020  * 000000 the color value of watermark is added to the destination.
00021  *
00022  * This way a mask that is visible both in light pictures and in dark can be
00023  * made (fex by using a picture generated by Gimp and the bump map tool).
00024  *
00025  * An example watermark file is at
00026  * http://engene.se/ffmpeg_watermark.gif
00027  *
00028  * MODE 1:
00029  * Per color do this:
00030  * If mask color > threshold color then the watermark pixel is used.
00031  *
00032  * Example usage:
00033  *  ffmpeg -i infile -vhook '/path/watermark.so -f wm.gif' -an out.mov
00034  *  ffmpeg -i infile -vhook '/path/watermark.so -f wm.gif -m 1 -t 222222' -an out.mov
00035  *
00036  * Note that the entire vhook argument is encapsulated in ''. This
00037  * way, arguments to the vhook won't be mixed up with those for ffmpeg.
00038  *
00039  * This file is part of FFmpeg.
00040  *
00041  * FFmpeg is free software; you can redistribute it and/or
00042  * modify it under the terms of the GNU Lesser General Public
00043  * License as published by the Free Software Foundation; either
00044  * version 2.1 of the License, or (at your option) any later version.
00045  *
00046  * FFmpeg is distributed in the hope that it will be useful,
00047  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00048  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00049  * Lesser General Public License for more details.
00050  *
00051  * You should have received a copy of the GNU Lesser General Public
00052  * License along with FFmpeg; if not, write to the Free Software
00053  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00054  */
00055 
00056 #include <stdlib.h>
00057 //#include <fcntl.h>
00058 #include <unistd.h>
00059 #include <stdarg.h>
00060 
00061 #include "libavutil/common.h"
00062 #include "libavformat/avformat.h"
00063 #include "libavformat/framehook.h"
00064 #include "libswscale/swscale.h"
00065 
00066 static int sws_flags = SWS_BICUBIC;
00067 
00068 typedef struct {
00069     char            filename[2000];
00070     int             x_size;
00071     int             y_size;
00072 
00073     /* get_watermark_picture() variables */
00074     AVFormatContext *pFormatCtx;
00075     const char     *p_ext;
00076     int             videoStream;
00077     int             frameFinished;
00078     AVCodecContext *pCodecCtx;
00079     AVCodec        *pCodec;
00080     AVFrame        *pFrame;
00081     AVPacket        packet;
00082     int             numBytes;
00083     uint8_t        *buffer;
00084     int             i;
00085     AVInputFormat  *file_iformat;
00086     AVStream       *st;
00087     int             is_done;
00088     AVFrame        *pFrameRGB;
00089     int             thrR;
00090     int             thrG;
00091     int             thrB;
00092     int             mode;
00093 
00094     // This vhook first converts frame to RGB ...
00095     struct SwsContext *toRGB_convert_ctx;
00096     // ... then converts a watermark and applies it to the RGB frame ...
00097     struct SwsContext *watermark_convert_ctx;
00098     // ... and finally converts back frame from RGB to initial format
00099     struct SwsContext *fromRGB_convert_ctx;
00100 } ContextInfo;
00101 
00102 int get_watermark_picture(ContextInfo *ci, int cleanup);
00103 
00104 
00105 /****************************************************************************
00106  *
00107  ****************************************************************************/
00108 void Release(void *ctx)
00109 {
00110     ContextInfo *ci;
00111     ci = (ContextInfo *) ctx;
00112 
00113     if (ci) {
00114         get_watermark_picture(ci, 1);
00115         sws_freeContext(ci->toRGB_convert_ctx);
00116         sws_freeContext(ci->watermark_convert_ctx);
00117         sws_freeContext(ci->fromRGB_convert_ctx);
00118     }
00119     av_free(ctx);
00120 }
00121 
00122 
00123 /****************************************************************************
00124  *
00125  ****************************************************************************/
00126 int Configure(void **ctxp, int argc, char *argv[])
00127 {
00128     ContextInfo *ci;
00129     int c;
00130     int tmp = 0;
00131 
00132     if (0 == (*ctxp = av_mallocz(sizeof(ContextInfo)))) return -1;
00133     ci = (ContextInfo *) *ctxp;
00134 
00135     optind = 1;
00136 
00137     // Struct is mallocz:ed so no need to reset.
00138     ci->thrR = 0x80;
00139     ci->thrG = 0x80;
00140     ci->thrB = 0x80;
00141 
00142     while ((c = getopt(argc, argv, "f:m:t:")) > 0) {
00143         switch (c) {
00144             case 'f':
00145                 strncpy(ci->filename, optarg, 1999);
00146                 ci->filename[1999] = 0;
00147                 break;
00148             case 'm':
00149                 ci->mode = atoi(optarg);
00150                 break;
00151             case 't':
00152                 if (1 != sscanf(optarg, "%x", &tmp)) {
00153                     av_log(NULL, AV_LOG_ERROR, "Watermark: argument to -t must be a 6 digit hex number\n");
00154                     return -1;
00155                 }
00156                 ci->thrR = (tmp >> 16) & 0xff;
00157                 ci->thrG = (tmp >> 8) & 0xff;
00158                 ci->thrB = (tmp >> 0) & 0xff;
00159                 break;
00160             default:
00161                 av_log(NULL, AV_LOG_ERROR, "Watermark: Unrecognized argument '%s'\n", argv[optind]);
00162                 return -1;
00163         }
00164     }
00165 
00166     //
00167     if (0 == ci->filename[0]) {
00168         av_log(NULL, AV_LOG_ERROR, "Watermark: There is no filename specified.\n");
00169         return -1;
00170     }
00171 
00172     av_register_all();
00173     return get_watermark_picture(ci, 0);
00174 }
00175 
00176 
00177 /****************************************************************************
00178  * For mode 0 (the original one)
00179  ****************************************************************************/
00180 static void Process0(void *ctx,
00181               AVPicture *picture,
00182               enum PixelFormat pix_fmt,
00183               int src_width,
00184               int src_height,
00185               int64_t pts)
00186 {
00187     ContextInfo *ci = (ContextInfo *) ctx;
00188     char *buf = 0;
00189     AVPicture picture1;
00190     AVPicture *pict = picture;
00191 
00192     AVFrame *pFrameRGB;
00193     int xm_size;
00194     int ym_size;
00195 
00196     int x;
00197     int y;
00198     int offs, offsm;
00199     int mpoffs;
00200     uint32_t *p_pixel = 0;
00201     uint32_t pixel_meck;
00202     uint32_t pixel;
00203     uint32_t pixelm;
00204     int tmp;
00205     int thrR = ci->thrR;
00206     int thrG = ci->thrG;
00207     int thrB = ci->thrB;
00208 
00209     if (pix_fmt != PIX_FMT_RGB32) {
00210         int size;
00211 
00212         size = avpicture_get_size(PIX_FMT_RGB32, src_width, src_height);
00213         buf = av_malloc(size);
00214 
00215         avpicture_fill(&picture1, buf, PIX_FMT_RGB32, src_width, src_height);
00216 
00217         // if we already got a SWS context, let's realloc if is not re-useable
00218         ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx,
00219                                     src_width, src_height, pix_fmt,
00220                                     src_width, src_height, PIX_FMT_RGB32,
00221                                     sws_flags, NULL, NULL, NULL);
00222         if (ci->toRGB_convert_ctx == NULL) {
00223             av_log(NULL, AV_LOG_ERROR,
00224                    "Cannot initialize the toRGB conversion context\n");
00225             return;
00226         }
00227 
00228 // img_convert parameters are          2 first destination, then 4 source
00229 // sws_scale   parameters are context, 4 first source,      then 2 destination
00230         sws_scale(ci->toRGB_convert_ctx,
00231                  picture->data, picture->linesize, 0, src_height,
00232                  picture1.data, picture1.linesize);
00233 
00234         pict = &picture1;
00235     }
00236 
00237     /* Insert filter code here */ /* ok */
00238 
00239     // Get me next frame
00240     if (0 > get_watermark_picture(ci, 0)) {
00241         return;
00242     }
00243     // These are the three original static variables in the ffmpeg hack.
00244     pFrameRGB = ci->pFrameRGB;
00245     xm_size = ci->x_size;
00246     ym_size = ci->y_size;
00247 
00248     // I'll do the *4 => <<2 crap later. Most compilers understand that anyway.
00249     // According to avcodec.h PIX_FMT_RGB32 is handled in endian specific manner.
00250     for (y=0; y<src_height; y++) {
00251         offs = y * (src_width * 4);
00252         offsm = (((y * ym_size) / src_height) * 4) * xm_size; // offsm first in maskline. byteoffs!
00253         for (x=0; x<src_width; x++) {
00254             mpoffs = offsm + (((x * xm_size) / src_width) * 4);
00255             p_pixel = (uint32_t *)&((pFrameRGB->data[0])[mpoffs]);
00256             pixelm = *p_pixel;
00257             p_pixel = (uint32_t *)&((pict->data[0])[offs]);
00258             pixel = *p_pixel;
00259 //          pixelm = *((uint32_t *)&(pFrameRGB->data[mpoffs]));
00260             pixel_meck = pixel & 0xff000000;
00261 
00262             // R
00263             tmp = (int)((pixel >> 16) & 0xff) + (int)((pixelm >> 16) & 0xff) - thrR;
00264             if (tmp > 255) tmp = 255;
00265             if (tmp < 0) tmp = 0;
00266             pixel_meck |= (tmp << 16) & 0xff0000;
00267             // G
00268             tmp = (int)((pixel >> 8) & 0xff) + (int)((pixelm >> 8) & 0xff) - thrG;
00269             if (tmp > 255) tmp = 255;
00270             if (tmp < 0) tmp = 0;
00271             pixel_meck |= (tmp << 8) & 0xff00;
00272             // B
00273             tmp = (int)((pixel >> 0) & 0xff) + (int)((pixelm >> 0) & 0xff) - thrB;
00274             if (tmp > 255) tmp = 255;
00275             if (tmp < 0) tmp = 0;
00276             pixel_meck |= (tmp << 0) & 0xff;
00277 
00278 
00279             // test:
00280             //pixel_meck = pixel & 0xff000000;
00281             //pixel_meck |= (pixelm & 0x00ffffff);
00282 
00283             *p_pixel = pixel_meck;
00284 
00285             offs += 4;
00286         } // foreach X
00287     } // foreach Y
00288 
00289 
00290 
00291 
00292     if (pix_fmt != PIX_FMT_RGB32) {
00293         ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx,
00294                                       src_width, src_height, PIX_FMT_RGB32,
00295                                       src_width, src_height, pix_fmt,
00296                                       sws_flags, NULL, NULL, NULL);
00297         if (ci->fromRGB_convert_ctx == NULL) {
00298             av_log(NULL, AV_LOG_ERROR,
00299                    "Cannot initialize the fromRGB conversion context\n");
00300             return;
00301         }
00302 // img_convert parameters are          2 first destination, then 4 source
00303 // sws_scale   parameters are context, 4 first source,      then 2 destination
00304         sws_scale(ci->fromRGB_convert_ctx,
00305                  picture1.data, picture1.linesize, 0, src_height,
00306                  picture->data, picture->linesize);
00307     }
00308 
00309     av_free(buf);
00310 }
00311 
00312 
00313 /****************************************************************************
00314  * For mode 1 (the original one)
00315  ****************************************************************************/
00316 static void Process1(void *ctx,
00317               AVPicture *picture,
00318               enum PixelFormat pix_fmt,
00319               int src_width,
00320               int src_height,
00321               int64_t pts)
00322 {
00323     ContextInfo *ci = (ContextInfo *) ctx;
00324     char *buf = 0;
00325     AVPicture picture1;
00326     AVPicture *pict = picture;
00327 
00328     AVFrame *pFrameRGB;
00329     int xm_size;
00330     int ym_size;
00331 
00332     int x;
00333     int y;
00334     int offs, offsm;
00335     int mpoffs;
00336     uint32_t *p_pixel = 0;
00337     uint32_t pixel;
00338     uint32_t pixelm;
00339 
00340     if (pix_fmt != PIX_FMT_RGB32) {
00341         int size;
00342 
00343         size = avpicture_get_size(PIX_FMT_RGB32, src_width, src_height);
00344         buf = av_malloc(size);
00345 
00346         avpicture_fill(&picture1, buf, PIX_FMT_RGB32, src_width, src_height);
00347 
00348         // if we already got a SWS context, let's realloc if is not re-useable
00349         ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx,
00350                                     src_width, src_height, pix_fmt,
00351                                     src_width, src_height, PIX_FMT_RGB32,
00352                                     sws_flags, NULL, NULL, NULL);
00353         if (ci->toRGB_convert_ctx == NULL) {
00354             av_log(NULL, AV_LOG_ERROR,
00355                    "Cannot initialize the toRGB conversion context\n");
00356             return;
00357         }
00358 
00359 // img_convert parameters are          2 first destination, then 4 source
00360 // sws_scale   parameters are context, 4 first source,      then 2 destination
00361         sws_scale(ci->toRGB_convert_ctx,
00362                  picture->data, picture->linesize, 0, src_height,
00363                  picture1.data, picture1.linesize);
00364 
00365         pict = &picture1;
00366     }
00367 
00368     /* Insert filter code here */ /* ok */
00369 
00370     // Get me next frame
00371     if (0 > get_watermark_picture(ci, 0)) {
00372         return;
00373     }
00374     // These are the three original static variables in the ffmpeg hack.
00375     pFrameRGB = ci->pFrameRGB;
00376     xm_size = ci->x_size;
00377     ym_size = ci->y_size;
00378 
00379     // I'll do the *4 => <<2 crap later. Most compilers understand that anyway.
00380     // According to avcodec.h PIX_FMT_RGB32 is handled in endian specific manner.
00381     for (y=0; y<src_height; y++) {
00382         offs = y * (src_width * 4);
00383         offsm = (((y * ym_size) / src_height) * 4) * xm_size; // offsm first in maskline. byteoffs!
00384         for (x=0; x<src_width; x++) {
00385             mpoffs = offsm + (((x * xm_size) / src_width) * 4);
00386             p_pixel = (uint32_t *)&((pFrameRGB->data[0])[mpoffs]);
00387             pixelm = *p_pixel; /* watermark pixel */
00388             p_pixel = (uint32_t *)&((pict->data[0])[offs]);
00389             pixel = *p_pixel;
00390 
00391             if (((pixelm >> 16) & 0xff) > ci->thrR ||
00392                 ((pixelm >>  8) & 0xff) > ci->thrG ||
00393                 ((pixelm >>  0) & 0xff) > ci->thrB)
00394             {
00395                 *p_pixel = pixelm;
00396             } else {
00397                 *p_pixel = pixel;
00398             }
00399             offs += 4;
00400         } // foreach X
00401     } // foreach Y
00402 
00403     if (pix_fmt != PIX_FMT_RGB32) {
00404         ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx,
00405                                       src_width, src_height, PIX_FMT_RGB32,
00406                                       src_width, src_height, pix_fmt,
00407                                       sws_flags, NULL, NULL, NULL);
00408         if (ci->fromRGB_convert_ctx == NULL) {
00409             av_log(NULL, AV_LOG_ERROR,
00410                    "Cannot initialize the fromRGB conversion context\n");
00411             return;
00412         }
00413 // img_convert parameters are          2 first destination, then 4 source
00414 // sws_scale   parameters are context, 4 first source,      then 2 destination
00415         sws_scale(ci->fromRGB_convert_ctx,
00416                  picture1.data, picture1.linesize, 0, src_height,
00417                  picture->data, picture->linesize);
00418     }
00419 
00420     av_free(buf);
00421 }
00422 
00423 
00424 /****************************************************************************
00425  * This is the function ffmpeg.c callbacks.
00426  ****************************************************************************/
00427 void Process(void *ctx,
00428              AVPicture *picture,
00429              enum PixelFormat pix_fmt,
00430              int src_width,
00431              int src_height,
00432              int64_t pts)
00433 {
00434     ContextInfo *ci = (ContextInfo *) ctx;
00435     if (1 == ci->mode) {
00436         Process1(ctx, picture, pix_fmt, src_width, src_height, pts);
00437     } else {
00438         Process0(ctx, picture, pix_fmt, src_width, src_height, pts);
00439     }
00440 }
00441 
00442 
00443 /****************************************************************************
00444  * When cleanup == 0, we try to get the next frame. If no next frame, nothing
00445  * is done.
00446  *
00447  * This code follows the example on
00448  * http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html
00449  *
00450  * 0 = ok, -1 = error
00451  ****************************************************************************/
00452 int get_watermark_picture(ContextInfo *ci, int cleanup)
00453 {
00454     if (1 == ci->is_done && 0 == cleanup) return 0;
00455 
00456     // Yes, *pFrameRGB arguments must be null the first time otherwise it's not good..
00457     // This block is only executed the first time we enter this function.
00458     if (0 == ci->pFrameRGB &&
00459         0 == cleanup)
00460     {
00461 
00462         /*
00463          * The last three parameters specify the file format, buffer size and format
00464          * parameters; by simply specifying NULL or 0 we ask libavformat to auto-detect
00465          * the format and use a default buffer size. (Didn't work!)
00466          */
00467         if (av_open_input_file(&ci->pFormatCtx, ci->filename, NULL, 0, NULL) != 0) {
00468 
00469             // Martin says this should not be necessary but it failed for me sending in
00470             // NULL instead of file_iformat to av_open_input_file()
00471             ci->i = strlen(ci->filename);
00472             if (0 == ci->i) {
00473                 av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() No filename to watermark vhook\n");
00474                 return -1;
00475             }
00476             while (ci->i > 0) {
00477                 if (ci->filename[ci->i] == '.') {
00478                     ci->i++;
00479                     break;
00480                 }
00481                 ci->i--;
00482             }
00483                ci->p_ext = &(ci->filename[ci->i]);
00484             ci->file_iformat = av_find_input_format (ci->p_ext);
00485             if (0 == ci->file_iformat) {
00486                 av_log(NULL, AV_LOG_INFO, "get_watermark_picture() attempt to use image2 for [%s]\n", ci->p_ext);
00487                 ci->file_iformat = av_find_input_format ("image2");
00488             }
00489             if (0 == ci->file_iformat) {
00490                 av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Really failed to find iformat [%s]\n", ci->p_ext);
00491                 return -1;
00492             }
00493             // now continues the Martin template.
00494 
00495             if (av_open_input_file(&ci->pFormatCtx, ci->filename, ci->file_iformat, 0, NULL)!=0) {
00496                 av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to open input file [%s]\n", ci->filename);
00497                 return -1;
00498             }
00499         }
00500 
00501         /*
00502          * This fills the streams field of the AVFormatContext with valid information.
00503          */
00504         if(av_find_stream_info(ci->pFormatCtx)<0) {
00505             av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find stream info\n");
00506             return -1;
00507         }
00508 
00509         /*
00510          * As mentioned in the introduction, we'll handle only video streams, not audio
00511          * streams. To make things nice and easy, we simply use the first video stream we
00512          * find.
00513          */
00514         ci->videoStream=-1;
00515         for(ci->i = 0; ci->i < ci->pFormatCtx->nb_streams; ci->i++)
00516             if(ci->pFormatCtx->streams[ci->i]->codec->codec_type==CODEC_TYPE_VIDEO)
00517             {
00518                 ci->videoStream = ci->i;
00519                 break;
00520             }
00521         if(ci->videoStream == -1) {
00522             av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find any video stream\n");
00523             return -1;
00524         }
00525 
00526         ci->st = ci->pFormatCtx->streams[ci->videoStream];
00527         ci->x_size = ci->st->codec->width;
00528         ci->y_size = ci->st->codec->height;
00529 
00530         // Get a pointer to the codec context for the video stream
00531         ci->pCodecCtx = ci->pFormatCtx->streams[ci->videoStream]->codec;
00532 
00533 
00534         /*
00535          * OK, so now we've got a pointer to the so-called codec context for our video
00536          * stream, but we still have to find the actual codec and open it.
00537          */
00538         // Find the decoder for the video stream
00539         ci->pCodec = avcodec_find_decoder(ci->pCodecCtx->codec_id);
00540         if(ci->pCodec == NULL) {
00541             av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find any codec\n");
00542             return -1;
00543         }
00544 
00545 
00546         // Open codec
00547         if(avcodec_open(ci->pCodecCtx, ci->pCodec)<0) {
00548             av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to open codec\n");
00549             return -1;
00550         }
00551 
00552         // Hack to correct wrong frame rates that seem to be generated by some
00553         // codecs
00554         if (ci->pCodecCtx->time_base.den>1000 && ci->pCodecCtx->time_base.num==1)
00555             ci->pCodecCtx->time_base.num=1000;
00556 
00557         /*
00558          * Allocate a video frame to store the decoded images in.
00559          */
00560         ci->pFrame = avcodec_alloc_frame();
00561 
00562 
00563         /*
00564          * The RGB image pFrameRGB (of type AVFrame *) is allocated like this:
00565          */
00566         // Allocate an AVFrame structure
00567         ci->pFrameRGB=avcodec_alloc_frame();
00568         if(ci->pFrameRGB==NULL) {
00569             av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to alloc pFrameRGB\n");
00570             return -1;
00571         }
00572 
00573         // Determine required buffer size and allocate buffer
00574         ci->numBytes = avpicture_get_size(PIX_FMT_RGB32, ci->pCodecCtx->width,
00575             ci->pCodecCtx->height);
00576         ci->buffer = av_malloc(ci->numBytes);
00577 
00578         // Assign appropriate parts of buffer to image planes in pFrameRGB
00579         avpicture_fill((AVPicture *)ci->pFrameRGB, ci->buffer, PIX_FMT_RGB32,
00580             ci->pCodecCtx->width, ci->pCodecCtx->height);
00581     }
00582     // TODO loop, pingpong etc?
00583     if (0 == cleanup)
00584     {
00585 //        av_log(NULL, AV_LOG_DEBUG, "get_watermark_picture() Get a frame\n");
00586         while(av_read_frame(ci->pFormatCtx, &ci->packet)>=0)
00587         {
00588             // Is this a packet from the video stream?
00589             if(ci->packet.stream_index == ci->videoStream)
00590             {
00591                 // Decode video frame
00592                 avcodec_decode_video(ci->pCodecCtx, ci->pFrame, &ci->frameFinished,
00593                     ci->packet.data, ci->packet.size);
00594 
00595                 // Did we get a video frame?
00596                 if(ci->frameFinished)
00597                 {
00598                     // Convert the image from its native format to RGB32
00599                     ci->watermark_convert_ctx =
00600                         sws_getCachedContext(ci->watermark_convert_ctx,
00601                             ci->pCodecCtx->width, ci->pCodecCtx->height, ci->pCodecCtx->pix_fmt,
00602                             ci->pCodecCtx->width, ci->pCodecCtx->height, PIX_FMT_RGB32,
00603                             sws_flags, NULL, NULL, NULL);
00604                     if (ci->watermark_convert_ctx == NULL) {
00605                         av_log(NULL, AV_LOG_ERROR,
00606                               "Cannot initialize the watermark conversion context\n");
00607                         return -1;
00608                     }
00609 // img_convert parameters are          2 first destination, then 4 source
00610 // sws_scale   parameters are context, 4 first source,      then 2 destination
00611                     sws_scale(ci->watermark_convert_ctx,
00612                              ci->pFrame->data, ci->pFrame->linesize, 0, ci->pCodecCtx->height,
00613                              ci->pFrameRGB->data, ci->pFrameRGB->linesize);
00614 
00615                     // Process the video frame (save to disk etc.)
00616                     //fprintf(stderr,"banan() New frame!\n");
00617                     //DoSomethingWithTheImage(ci->pFrameRGB);
00618                     return 0;
00619                 }
00620             }
00621 
00622             // Free the packet that was allocated by av_read_frame
00623             av_free_packet(&ci->packet);
00624         }
00625         ci->is_done = 1;
00626         return 0;
00627     } // if 0 != cleanup
00628 
00629     if (0 != cleanup)
00630     {
00631         // Free the RGB image
00632         av_freep(&ci->buffer);
00633         av_freep(&ci->pFrameRGB);
00634 
00635         // Close the codec
00636         if (0 != ci->pCodecCtx) {
00637             avcodec_close(ci->pCodecCtx);
00638             ci->pCodecCtx = 0;
00639         }
00640 
00641         // Close the video file
00642         if (0 != ci->pFormatCtx) {
00643             av_close_input_file(ci->pFormatCtx);
00644             ci->pFormatCtx = 0;
00645         }
00646 
00647         ci->is_done = 0;
00648     }
00649     return 0;
00650 }
00651 
00652 
00653 void parse_arg_file(const char *filename)
00654 {
00655 }

Generated on Sat Feb 16 2013 09:23:15 for ffmpeg by  doxygen 1.7.1