00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #include <stdlib.h>
00057
00058 #include <unistd.h>
00059 #include <stdarg.h>
00060
00061 #include "common.h"
00062 #include "avformat.h"
00063
00064 #include "framehook.h"
00065 #include "cmdutils.h"
00066 #include "swscale.h"
00067
00068 static int sws_flags = SWS_BICUBIC;
00069
00070 typedef struct {
00071 char filename[2000];
00072 int x_size;
00073 int y_size;
00074
00075
00076 AVFormatContext *pFormatCtx;
00077 const char *p_ext;
00078 int videoStream;
00079 int frameFinished;
00080 AVCodecContext *pCodecCtx;
00081 AVCodec *pCodec;
00082 AVFrame *pFrame;
00083 AVPacket packet;
00084 int numBytes;
00085 uint8_t *buffer;
00086 int i;
00087 AVInputFormat *file_iformat;
00088 AVStream *st;
00089 int is_done;
00090 AVFrame *pFrameRGB;
00091 int thrR;
00092 int thrG;
00093 int thrB;
00094 int mode;
00095
00096
00097 struct SwsContext *toRGB_convert_ctx;
00098
00099 struct SwsContext *watermark_convert_ctx;
00100
00101 struct SwsContext *fromRGB_convert_ctx;
00102 } ContextInfo;
00103
00104 int get_watermark_picture(ContextInfo *ci, int cleanup);
00105
00106
00107
00108
00109
00110 void Release(void *ctx)
00111 {
00112 ContextInfo *ci;
00113 ci = (ContextInfo *) ctx;
00114
00115 if (ci) {
00116 get_watermark_picture(ci, 1);
00117 sws_freeContext(ci->toRGB_convert_ctx);
00118 sws_freeContext(ci->watermark_convert_ctx);
00119 sws_freeContext(ci->fromRGB_convert_ctx);
00120 }
00121 av_free(ctx);
00122 }
00123
00124
00125
00126
00127
00128 int Configure(void **ctxp, int argc, char *argv[])
00129 {
00130 ContextInfo *ci;
00131 int c;
00132 int tmp = 0;
00133
00134 if (0 == (*ctxp = av_mallocz(sizeof(ContextInfo)))) return -1;
00135 ci = (ContextInfo *) *ctxp;
00136
00137 optind = 1;
00138
00139
00140 ci->thrR = 0x80;
00141 ci->thrG = 0x80;
00142 ci->thrB = 0x80;
00143
00144 while ((c = getopt(argc, argv, "f:m:t:")) > 0) {
00145 switch (c) {
00146 case 'f':
00147 strncpy(ci->filename, optarg, 1999);
00148 ci->filename[1999] = 0;
00149 break;
00150 case 'm':
00151 ci->mode = atoi(optarg);
00152 break;
00153 case 't':
00154 if (1 != sscanf(optarg, "%x", &tmp)) {
00155 av_log(NULL, AV_LOG_ERROR, "Watermark: argument to -t must be a 6 digit hex number\n");
00156 return -1;
00157 }
00158 ci->thrR = (tmp >> 16) & 0xff;
00159 ci->thrG = (tmp >> 8) & 0xff;
00160 ci->thrB = (tmp >> 0) & 0xff;
00161 break;
00162 default:
00163 av_log(NULL, AV_LOG_ERROR, "Watermark: Unrecognized argument '%s'\n", argv[optind]);
00164 return -1;
00165 }
00166 }
00167
00168
00169 if (0 == ci->filename[0]) {
00170 av_log(NULL, AV_LOG_ERROR, "Watermark: There is no filename specified.\n");
00171 return -1;
00172 }
00173
00174 av_register_all();
00175 return get_watermark_picture(ci, 0);
00176 }
00177
00178
00179
00180
00181
00182 static void Process0(void *ctx,
00183 AVPicture *picture,
00184 enum PixelFormat pix_fmt,
00185 int src_width,
00186 int src_height,
00187 int64_t pts)
00188 {
00189 ContextInfo *ci = (ContextInfo *) ctx;
00190 char *buf = 0;
00191 AVPicture picture1;
00192 AVPicture *pict = picture;
00193
00194 AVFrame *pFrameRGB;
00195 int xm_size;
00196 int ym_size;
00197
00198 int x;
00199 int y;
00200 int offs, offsm;
00201 int mpoffs;
00202 uint32_t *p_pixel = 0;
00203 uint32_t pixel_meck;
00204 uint32_t pixel;
00205 uint32_t pixelm;
00206 int tmp;
00207 int thrR = ci->thrR;
00208 int thrG = ci->thrG;
00209 int thrB = ci->thrB;
00210
00211 if (pix_fmt != PIX_FMT_RGB32) {
00212 int size;
00213
00214 size = avpicture_get_size(PIX_FMT_RGB32, src_width, src_height);
00215 buf = av_malloc(size);
00216
00217 avpicture_fill(&picture1, buf, PIX_FMT_RGB32, src_width, src_height);
00218
00219
00220 ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx,
00221 src_width, src_height, pix_fmt,
00222 src_width, src_height, PIX_FMT_RGB32,
00223 sws_flags, NULL, NULL, NULL);
00224 if (ci->toRGB_convert_ctx == NULL) {
00225 av_log(NULL, AV_LOG_ERROR,
00226 "Cannot initialize the toRGB conversion context\n");
00227 return;
00228 }
00229
00230
00231
00232 sws_scale(ci->toRGB_convert_ctx,
00233 picture->data, picture->linesize, 0, src_height,
00234 picture1.data, picture1.linesize);
00235
00236 pict = &picture1;
00237 }
00238
00239
00240
00241
00242 if (0 > get_watermark_picture(ci, 0)) {
00243 return;
00244 }
00245
00246 pFrameRGB = ci->pFrameRGB;
00247 xm_size = ci->x_size;
00248 ym_size = ci->y_size;
00249
00250
00251
00252 for (y=0; y<src_height; y++) {
00253 offs = y * (src_width * 4);
00254 offsm = (((y * ym_size) / src_height) * 4) * xm_size;
00255 for (x=0; x<src_width; x++) {
00256 mpoffs = offsm + (((x * xm_size) / src_width) * 4);
00257 p_pixel = (uint32_t *)&((pFrameRGB->data[0])[mpoffs]);
00258 pixelm = *p_pixel;
00259 p_pixel = (uint32_t *)&((pict->data[0])[offs]);
00260 pixel = *p_pixel;
00261
00262 pixel_meck = pixel & 0xff000000;
00263
00264
00265 tmp = (int)((pixel >> 16) & 0xff) + (int)((pixelm >> 16) & 0xff) - thrR;
00266 if (tmp > 255) tmp = 255;
00267 if (tmp < 0) tmp = 0;
00268 pixel_meck |= (tmp << 16) & 0xff0000;
00269
00270 tmp = (int)((pixel >> 8) & 0xff) + (int)((pixelm >> 8) & 0xff) - thrG;
00271 if (tmp > 255) tmp = 255;
00272 if (tmp < 0) tmp = 0;
00273 pixel_meck |= (tmp << 8) & 0xff00;
00274
00275 tmp = (int)((pixel >> 0) & 0xff) + (int)((pixelm >> 0) & 0xff) - thrB;
00276 if (tmp > 255) tmp = 255;
00277 if (tmp < 0) tmp = 0;
00278 pixel_meck |= (tmp << 0) & 0xff;
00279
00280
00281
00282
00283
00284
00285 *p_pixel = pixel_meck;
00286
00287 offs += 4;
00288 }
00289 }
00290
00291
00292
00293
00294 if (pix_fmt != PIX_FMT_RGB32) {
00295 ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx,
00296 src_width, src_height, PIX_FMT_RGB32,
00297 src_width, src_height, pix_fmt,
00298 sws_flags, NULL, NULL, NULL);
00299 if (ci->fromRGB_convert_ctx == NULL) {
00300 av_log(NULL, AV_LOG_ERROR,
00301 "Cannot initialize the fromRGB conversion context\n");
00302 return;
00303 }
00304
00305
00306 sws_scale(ci->fromRGB_convert_ctx,
00307 picture1.data, picture1.linesize, 0, src_height,
00308 picture->data, picture->linesize);
00309 }
00310
00311 av_free(buf);
00312 }
00313
00314
00315
00316
00317
00318 static void Process1(void *ctx,
00319 AVPicture *picture,
00320 enum PixelFormat pix_fmt,
00321 int src_width,
00322 int src_height,
00323 int64_t pts)
00324 {
00325 ContextInfo *ci = (ContextInfo *) ctx;
00326 char *buf = 0;
00327 AVPicture picture1;
00328 AVPicture *pict = picture;
00329
00330 AVFrame *pFrameRGB;
00331 int xm_size;
00332 int ym_size;
00333
00334 int x;
00335 int y;
00336 int offs, offsm;
00337 int mpoffs;
00338 uint32_t *p_pixel = 0;
00339 uint32_t pixel;
00340 uint32_t pixelm;
00341
00342 if (pix_fmt != PIX_FMT_RGB32) {
00343 int size;
00344
00345 size = avpicture_get_size(PIX_FMT_RGB32, src_width, src_height);
00346 buf = av_malloc(size);
00347
00348 avpicture_fill(&picture1, buf, PIX_FMT_RGB32, src_width, src_height);
00349
00350
00351 ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx,
00352 src_width, src_height, pix_fmt,
00353 src_width, src_height, PIX_FMT_RGB32,
00354 sws_flags, NULL, NULL, NULL);
00355 if (ci->toRGB_convert_ctx == NULL) {
00356 av_log(NULL, AV_LOG_ERROR,
00357 "Cannot initialize the toRGB conversion context\n");
00358 return;
00359 }
00360
00361
00362
00363 sws_scale(ci->toRGB_convert_ctx,
00364 picture->data, picture->linesize, 0, src_height,
00365 picture1.data, picture1.linesize);
00366
00367 pict = &picture1;
00368 }
00369
00370
00371
00372
00373 if (0 > get_watermark_picture(ci, 0)) {
00374 return;
00375 }
00376
00377 pFrameRGB = ci->pFrameRGB;
00378 xm_size = ci->x_size;
00379 ym_size = ci->y_size;
00380
00381
00382
00383 for (y=0; y<src_height; y++) {
00384 offs = y * (src_width * 4);
00385 offsm = (((y * ym_size) / src_height) * 4) * xm_size;
00386 for (x=0; x<src_width; x++) {
00387 mpoffs = offsm + (((x * xm_size) / src_width) * 4);
00388 p_pixel = (uint32_t *)&((pFrameRGB->data[0])[mpoffs]);
00389 pixelm = *p_pixel;
00390 p_pixel = (uint32_t *)&((pict->data[0])[offs]);
00391 pixel = *p_pixel;
00392
00393 if (((pixelm >> 16) & 0xff) > ci->thrR ||
00394 ((pixelm >> 8) & 0xff) > ci->thrG ||
00395 ((pixelm >> 0) & 0xff) > ci->thrB)
00396 {
00397 *p_pixel = pixelm;
00398 } else {
00399 *p_pixel = pixel;
00400 }
00401 offs += 4;
00402 }
00403 }
00404
00405 if (pix_fmt != PIX_FMT_RGB32) {
00406 ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx,
00407 src_width, src_height, PIX_FMT_RGB32,
00408 src_width, src_height, pix_fmt,
00409 sws_flags, NULL, NULL, NULL);
00410 if (ci->fromRGB_convert_ctx == NULL) {
00411 av_log(NULL, AV_LOG_ERROR,
00412 "Cannot initialize the fromRGB conversion context\n");
00413 return;
00414 }
00415
00416
00417 sws_scale(ci->fromRGB_convert_ctx,
00418 picture1.data, picture1.linesize, 0, src_height,
00419 picture->data, picture->linesize);
00420 }
00421
00422 av_free(buf);
00423 }
00424
00425
00426
00427
00428
00429 void Process(void *ctx,
00430 AVPicture *picture,
00431 enum PixelFormat pix_fmt,
00432 int src_width,
00433 int src_height,
00434 int64_t pts)
00435 {
00436 ContextInfo *ci = (ContextInfo *) ctx;
00437 if (1 == ci->mode) {
00438 Process1(ctx, picture, pix_fmt, src_width, src_height, pts);
00439 } else {
00440 Process0(ctx, picture, pix_fmt, src_width, src_height, pts);
00441 }
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 int get_watermark_picture(ContextInfo *ci, int cleanup)
00455 {
00456 if (1 == ci->is_done && 0 == cleanup) return 0;
00457
00458
00459
00460 if (0 == ci->pFrameRGB &&
00461 0 == cleanup)
00462 {
00463
00464
00465
00466
00467
00468
00469 if (av_open_input_file(&ci->pFormatCtx, ci->filename, NULL, 0, NULL) != 0) {
00470
00471
00472
00473 ci->i = strlen(ci->filename);
00474 if (0 == ci->i) {
00475 av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() No filename to watermark vhook\n");
00476 return -1;
00477 }
00478 while (ci->i > 0) {
00479 if (ci->filename[ci->i] == '.') {
00480 ci->i++;
00481 break;
00482 }
00483 ci->i--;
00484 }
00485 ci->p_ext = &(ci->filename[ci->i]);
00486 ci->file_iformat = av_find_input_format (ci->p_ext);
00487 if (0 == ci->file_iformat) {
00488 av_log(NULL, AV_LOG_INFO, "get_watermark_picture() attempt to use image2 for [%s]\n", ci->p_ext);
00489 ci->file_iformat = av_find_input_format ("image2");
00490 }
00491 if (0 == ci->file_iformat) {
00492 av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Really failed to find iformat [%s]\n", ci->p_ext);
00493 return -1;
00494 }
00495
00496
00497 if (av_open_input_file(&ci->pFormatCtx, ci->filename, ci->file_iformat, 0, NULL)!=0) {
00498 av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to open input file [%s]\n", ci->filename);
00499 return -1;
00500 }
00501 }
00502
00503
00504
00505
00506 if(av_find_stream_info(ci->pFormatCtx)<0) {
00507 av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find stream info\n");
00508 return -1;
00509 }
00510
00511
00512
00513
00514
00515
00516 ci->videoStream=-1;
00517 for(ci->i = 0; ci->i < ci->pFormatCtx->nb_streams; ci->i++)
00518 if(ci->pFormatCtx->streams[ci->i]->codec->codec_type==CODEC_TYPE_VIDEO)
00519 {
00520 ci->videoStream = ci->i;
00521 break;
00522 }
00523 if(ci->videoStream == -1) {
00524 av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find any video stream\n");
00525 return -1;
00526 }
00527
00528 ci->st = ci->pFormatCtx->streams[ci->videoStream];
00529 ci->x_size = ci->st->codec->width;
00530 ci->y_size = ci->st->codec->height;
00531
00532
00533 ci->pCodecCtx = ci->pFormatCtx->streams[ci->videoStream]->codec;
00534
00535
00536
00537
00538
00539
00540
00541 ci->pCodec = avcodec_find_decoder(ci->pCodecCtx->codec_id);
00542 if(ci->pCodec == NULL) {
00543 av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find any codec\n");
00544 return -1;
00545 }
00546
00547
00548
00549 if(avcodec_open(ci->pCodecCtx, ci->pCodec)<0) {
00550 av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to open codec\n");
00551 return -1;
00552 }
00553
00554
00555
00556 if (ci->pCodecCtx->time_base.den>1000 && ci->pCodecCtx->time_base.num==1)
00557 ci->pCodecCtx->time_base.num=1000;
00558
00559
00560
00561
00562 ci->pFrame = avcodec_alloc_frame();
00563
00564
00565
00566
00567
00568
00569 ci->pFrameRGB=avcodec_alloc_frame();
00570 if(ci->pFrameRGB==NULL) {
00571 av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to alloc pFrameRGB\n");
00572 return -1;
00573 }
00574
00575
00576 ci->numBytes = avpicture_get_size(PIX_FMT_RGB32, ci->pCodecCtx->width,
00577 ci->pCodecCtx->height);
00578 ci->buffer = av_malloc(ci->numBytes);
00579
00580
00581 avpicture_fill((AVPicture *)ci->pFrameRGB, ci->buffer, PIX_FMT_RGB32,
00582 ci->pCodecCtx->width, ci->pCodecCtx->height);
00583 }
00584
00585 if (0 == cleanup)
00586 {
00587
00588 while(av_read_frame(ci->pFormatCtx, &ci->packet)>=0)
00589 {
00590
00591 if(ci->packet.stream_index == ci->videoStream)
00592 {
00593
00594 avcodec_decode_video(ci->pCodecCtx, ci->pFrame, &ci->frameFinished,
00595 ci->packet.data, ci->packet.size);
00596
00597
00598 if(ci->frameFinished)
00599 {
00600
00601 ci->watermark_convert_ctx =
00602 sws_getCachedContext(ci->watermark_convert_ctx,
00603 ci->pCodecCtx->width, ci->pCodecCtx->height, ci->pCodecCtx->pix_fmt,
00604 ci->pCodecCtx->width, ci->pCodecCtx->height, PIX_FMT_RGB32,
00605 sws_flags, NULL, NULL, NULL);
00606 if (ci->watermark_convert_ctx == NULL) {
00607 av_log(NULL, AV_LOG_ERROR,
00608 "Cannot initialize the watermark conversion context\n");
00609 return -1;
00610 }
00611
00612
00613 sws_scale(ci->watermark_convert_ctx,
00614 ci->pFrame->data, ci->pFrame->linesize, 0, ci->pCodecCtx->height,
00615 ci->pFrameRGB->data, ci->pFrameRGB->linesize);
00616
00617
00618
00619
00620 return 0;
00621 }
00622 }
00623
00624
00625 av_free_packet(&ci->packet);
00626 }
00627 ci->is_done = 1;
00628 return 0;
00629 }
00630
00631 if (0 != cleanup)
00632 {
00633
00634 av_freep(&ci->buffer);
00635 av_freep(&ci->pFrameRGB);
00636
00637
00638 if (0 != ci->pCodecCtx) {
00639 avcodec_close(ci->pCodecCtx);
00640 ci->pCodecCtx = 0;
00641 }
00642
00643
00644 if (0 != ci->pFormatCtx) {
00645 av_close_input_file(ci->pFormatCtx);
00646 ci->pFormatCtx = 0;
00647 }
00648
00649 ci->is_done = 0;
00650 }
00651 return 0;
00652 }
00653
00654
00655 void parse_arg_file(const char *filename)
00656 {
00657 }