[MPlayer-users] Re: Video Filter for Black Frame Detect

Brian J. Murrell brian at interlinx.bc.ca
Thu May 1 22:08:23 CEST 2003


On Thu, 01 May 2003 11:57:41 -0700, usene wrote:

 
> I was thinking of doing a commercial detect for mplayer to skip through
> commercials during playback.  One method seems to be doing black frame
> detect.

Been there done that.  Abandoned the idea.  The reason is that you still
need to decode and analyse _every_ frame after you have detected a black
frame (group), looking for the next black frame (group) to know where the
end of the commercial is.

On my machine, this only ran about 2-3 times normal frame rate, which
meant it still took 10-15 seconds to find the end of a 30 second
commercial block.  I can do better with just ffwd/rew by 10 and 1 second
increments.

> I was thinking of writing a video filter to do black frame 
> detect.  Anyone done something like this before?  Something I can
borrow?

Here is mine.  It's old code, so it may or may not work.  Let me know how
you make out.

/* vf_blackframe.c
 *
 * search for black frames to mark the beginning and end of commercial
 * blocks
 *
 * (c) 2002-2003 Brian J. Murrell
 *
 * Can be used and reproduced under the terms of the GPL, version 2
 *
 */
#ifdef BFSEARCH
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#include "../config.h"
#include "../mp_msg.h"

#include "img_format.h"
#include "mp_image.h"
#include "vf.h"

#include "../libvo/fastmemcpy.h"
#include "../postproc/rgb2rgb.h"

//===========================================================================//

struct vf_priv_s {
	unsigned int black_amount, black_thresh, is_black, searching;
};

static int config(struct vf_instance_s* vf,
        int width, int height, int d_width, int d_height,
	unsigned int flags, unsigned int outfmt){
    return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
}

static void put_image(struct vf_instance_s* vf, mp_image_t *mpi){

    int x, y;
    unsigned int num_black=0, pct_black=0, lines=0;

    // last frame was black, so stop searching and reset is_black
//fprintf(stderr, "black=%d search=%d ", vf->priv->is_black, vf->priv->searching);
    if (vf->priv->is_black) {
//fprintf(stderr, "\n\n%d clear is_black\n\n", __LINE__);
	vf->priv->is_black=0;
//fprintf(stderr, "\n\n%d clear searching\n\n", __LINE__);
	vf->priv->searching=0;
    }

    if (!vf->priv->searching) {
	vf_next_put_image(vf,mpi);
fprintf(stderr, "\nnot searching for black frames, returning\n");
	return;
    }
else
fprintf(stderr, "\nsearching for black frames\n");

//    vf->priv->searching=0;
//    vf->priv->is_black=0;

    for (y=mpi->h/2; y<mpi->h; y++) {
	for (x=0; x<mpi->w; x++) {
	    if (mpi->planes[0][y*mpi->w+x]<vf->priv->black_thresh) {
		num_black++;
	    }
	}
	lines++;
	pct_black=num_black*100/(mpi->w*lines);
	if (pct_black<vf->priv->black_amount)
	    goto done;
    }
    for (y=mpi->h/2-1; y>-1; y--) {
	for (x=0; x<mpi->w; x++) {
	    if (mpi->planes[0][y*mpi->w+x]<vf->priv->black_thresh) {
		num_black++;
	    }
	}
	lines++;
	pct_black=num_black*100/(mpi->w*lines);
	if (pct_black<vf->priv->black_amount)
	    goto done;
    }
done:
fprintf(stderr, "\nlines=%3u, %x %3u \n", lines, mpi->planes[0][mpi->w*10+10],
		pct_black);

    if (pct_black>=vf->priv->black_amount)
	vf->priv->is_black=1;

    // skip all other image processing steps
    //vf_next_put_image(vf,mpi);
    return;
}

//===========================================================================//

static int control(struct vf_instance_s* vf, int request, void* data){
    switch(request){
    case VFCTRL_QUERY_IS_BLACK:
		*(unsigned int *)data = vf->priv->is_black;
		return CONTROL_TRUE;
    case VFCTRL_SEARCH_FOR_BLACK:
		vf->priv->searching=1;
		return CONTROL_TRUE;
    case VFCTRL_QUERY_IS_SEARCHING:
		*(unsigned int *)data = vf->priv->searching;
		return CONTROL_TRUE;
    }
    return vf_next_control(vf,request,data);
}

static int open(vf_instance_t *vf, char* args){
    vf->config=config;
    vf->put_image=put_image;
    vf->control=control;
    vf->priv=malloc(sizeof(struct vf_priv_s));

    vf->priv->black_amount=98;
    vf->priv->black_thresh=0x40;
    vf->priv->searching=0;

    if (args)
	sscanf(args, "%d:%d", &vf->priv->black_amount, &vf->priv->black_thresh);
    return 1;
}

vf_info_t vf_info_blackframe = {
    "detects black frames",
    "blackframe",
    "Brian J. Murrell",
    "Very useful for skipping commercials.  :-)",
    open
};

//===========================================================================//
#endif




More information about the MPlayer-users mailing list