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 "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
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
00095 struct SwsContext *toRGB_convert_ctx;
00096
00097 struct SwsContext *watermark_convert_ctx;
00098
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
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
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
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
00229
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
00238
00239
00240 if (0 > get_watermark_picture(ci, 0)) {
00241 return;
00242 }
00243
00244 pFrameRGB = ci->pFrameRGB;
00245 xm_size = ci->x_size;
00246 ym_size = ci->y_size;
00247
00248
00249
00250 for (y=0; y<src_height; y++) {
00251 offs = y * (src_width * 4);
00252 offsm = (((y * ym_size) / src_height) * 4) * xm_size;
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
00260 pixel_meck = pixel & 0xff000000;
00261
00262
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
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
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
00280
00281
00282
00283 *p_pixel = pixel_meck;
00284
00285 offs += 4;
00286 }
00287 }
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
00303
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
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
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
00360
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
00369
00370
00371 if (0 > get_watermark_picture(ci, 0)) {
00372 return;
00373 }
00374
00375 pFrameRGB = ci->pFrameRGB;
00376 xm_size = ci->x_size;
00377 ym_size = ci->y_size;
00378
00379
00380
00381 for (y=0; y<src_height; y++) {
00382 offs = y * (src_width * 4);
00383 offsm = (((y * ym_size) / src_height) * 4) * xm_size;
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;
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 }
00401 }
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
00414
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
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
00445
00446
00447
00448
00449
00450
00451
00452 int get_watermark_picture(ContextInfo *ci, int cleanup)
00453 {
00454 if (1 == ci->is_done && 0 == cleanup) return 0;
00455
00456
00457
00458 if (0 == ci->pFrameRGB &&
00459 0 == cleanup)
00460 {
00461
00462
00463
00464
00465
00466
00467 if (av_open_input_file(&ci->pFormatCtx, ci->filename, NULL, 0, NULL) != 0) {
00468
00469
00470
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
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
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
00511
00512
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
00531 ci->pCodecCtx = ci->pFormatCtx->streams[ci->videoStream]->codec;
00532
00533
00534
00535
00536
00537
00538
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
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
00553
00554 if (ci->pCodecCtx->time_base.den>1000 && ci->pCodecCtx->time_base.num==1)
00555 ci->pCodecCtx->time_base.num=1000;
00556
00557
00558
00559
00560 ci->pFrame = avcodec_alloc_frame();
00561
00562
00563
00564
00565
00566
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
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
00579 avpicture_fill((AVPicture *)ci->pFrameRGB, ci->buffer, PIX_FMT_RGB32,
00580 ci->pCodecCtx->width, ci->pCodecCtx->height);
00581 }
00582
00583 if (0 == cleanup)
00584 {
00585
00586 while(av_read_frame(ci->pFormatCtx, &ci->packet)>=0)
00587 {
00588
00589 if(ci->packet.stream_index == ci->videoStream)
00590 {
00591
00592 avcodec_decode_video(ci->pCodecCtx, ci->pFrame, &ci->frameFinished,
00593 ci->packet.data, ci->packet.size);
00594
00595
00596 if(ci->frameFinished)
00597 {
00598
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
00610
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
00616
00617
00618 return 0;
00619 }
00620 }
00621
00622
00623 av_free_packet(&ci->packet);
00624 }
00625 ci->is_done = 1;
00626 return 0;
00627 }
00628
00629 if (0 != cleanup)
00630 {
00631
00632 av_freep(&ci->buffer);
00633 av_freep(&ci->pFrameRGB);
00634
00635
00636 if (0 != ci->pCodecCtx) {
00637 avcodec_close(ci->pCodecCtx);
00638 ci->pCodecCtx = 0;
00639 }
00640
00641
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 }