view libmpcodecs/ve_divx4.c @ 7256:ec6dd0a29d93

Add the code that chooses a good X11 truecolor visual to the vo_x11 config() function. This is useful for framebuffers on Sun hardware, where we have multiple truecolor visuals of different depths available, and the root window typically runs at depth 8, yet there are 24 bit true color visuals available as well.
author jkeil
date Tue, 03 Sep 2002 18:10:42 +0000
parents 1e47c2e7aa8e
children dd32b0c95c95
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

#ifdef HAVE_DIVX4ENCORE

#include "codec-cfg.h"
#include "stream.h"
#include "demuxer.h"
#include "stheader.h"

#include "aviwrite.h"

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

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

#include "divx4_vbr.h"

extern int pass;
extern char* passtmpfile;
extern void mencoder_write_chunk(aviwrite_stream_t *s,int len,unsigned int flags);

#include <encore2.h>

#ifndef ENCORE_MAJOR_VERSION
#define ENCORE_MAJOR_VERSION 4000
#endif

ENC_PARAM divx4_param;
int divx4_crispness;

#include "cfgparser.h"

struct config divx4opts_conf[]={
	{"br", &divx4_param.bitrate, CONF_TYPE_INT, CONF_RANGE, 4, 24000000, NULL},
	{"rc_period", &divx4_param.rc_period, CONF_TYPE_INT, 0,0,0, NULL},
	{"rc_reaction_period", &divx4_param.rc_reaction_period, CONF_TYPE_INT, 0,0,0, NULL},
	{"rc_reaction_ratio", &divx4_param.rc_reaction_ratio, CONF_TYPE_INT, 0,0,0, NULL},
	{"min_quant", &divx4_param.min_quantizer, CONF_TYPE_INT, CONF_RANGE,0,32, NULL},
	{"max_quant", &divx4_param.max_quantizer, CONF_TYPE_INT, CONF_RANGE,0,32, NULL},
	{"key", &divx4_param.max_key_interval, CONF_TYPE_INT, CONF_MIN,0,0, NULL},
	{"deinterlace", &divx4_param.deinterlace, CONF_TYPE_FLAG, 0,0,1, NULL},
	{"q", &divx4_param.quality, CONF_TYPE_INT, CONF_RANGE, 1, 5, NULL},
	{"crispness", &divx4_crispness, CONF_TYPE_INT, CONF_RANGE,0,100, NULL},
#if ENCORE_MAJOR_VERSION >= 5010
	{"bidirect", &divx4_param.extensions.use_bidirect, CONF_TYPE_FLAG, 0,0,1, NULL},
	{"obmc", &divx4_param.extensions.obmc, CONF_TYPE_FLAG, 0,0,1, NULL},
	{"data_partitioning", &divx4_param.extensions.data_partitioning, CONF_TYPE_FLAG, 0,0,1, NULL},
	{"qpel", &divx4_param.extensions.quarter_pel, CONF_TYPE_FLAG, 0,0,1, NULL},
	{"intra_frame_threshold", &divx4_param.extensions.intra_frame_threshold, CONF_TYPE_INT, CONF_RANGE,1,100, NULL},
	{"psychovisual", &divx4_param.extensions.psychovisual, CONF_TYPE_FLAG, 0,0,1, NULL},
	{"testing_param", &divx4_param.extensions.testing_param, CONF_TYPE_FLAG, 0,0,1, NULL},
	{"gmc", &divx4_param.extensions.use_gmc, CONF_TYPE_FLAG, 0,0,1, NULL},
	{"interlace_mode", &divx4_param.extensions.interlace_mode, CONF_TYPE_INT, CONF_RANGE,0,2, NULL},
	{"temporal", &divx4_param.extensions.temporal_enable, CONF_TYPE_FLAG, 0,0,1, NULL},
	{"spatial", &divx4_param.extensions.spatial_passes, CONF_TYPE_INT, 0,0,1, NULL},
	{"mv_file", &divx4_param.extensions.mv_file, CONF_TYPE_STRING, 0,0,1, NULL},
#endif
	{"help", "TODO: divx4opts help!\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
	{NULL, NULL, 0, 0, 0, 0, NULL}
};

struct vf_priv_s {
    aviwrite_stream_t* mux;
    ENC_RESULT enc_result;
    ENC_FRAME enc_frame;
    void* enc_handle;
};

#define mux_v (vf->priv->mux)

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

    mux_v->bih->biWidth=width;
    mux_v->bih->biHeight=height;

    divx4_param.x_dim=width;
    divx4_param.y_dim=height;
    divx4_param.framerate=(float)mux_v->h.dwRate/mux_v->h.dwScale;
    mux_v->bih->biSizeImage=mux_v->bih->biWidth*mux_v->bih->biHeight*3;

    if(!divx4_param.bitrate) divx4_param.bitrate=800000;
    else if(divx4_param.bitrate<=16000) divx4_param.bitrate*=1000;
    if(!divx4_param.quality) divx4_param.quality=5; // the quality of compression ( 1 - fastest, 5 - best )

    // set some usefull defaults:
    if(!divx4_param.min_quantizer) divx4_param.min_quantizer=2;
    if(!divx4_param.max_quantizer) divx4_param.max_quantizer=31;
    if(!divx4_param.rc_period) divx4_param.rc_period=2000;
    if(!divx4_param.rc_reaction_period) divx4_param.rc_reaction_period=10;
    if(!divx4_param.rc_reaction_ratio) divx4_param.rc_reaction_ratio=20;

    divx4_param.handle=NULL;
    encore(NULL,ENC_OPT_INIT,&divx4_param,NULL);
    vf->priv->enc_handle=divx4_param.handle;
    switch(outfmt){
    case IMGFMT_YV12:	vf->priv->enc_frame.colorspace=ENC_CSP_YV12; break;
    case IMGFMT_IYUV:
    case IMGFMT_I420:	vf->priv->enc_frame.colorspace=ENC_CSP_I420; break;
    case IMGFMT_YUY2:	vf->priv->enc_frame.colorspace=ENC_CSP_YUY2; break;
    case IMGFMT_UYVY:	vf->priv->enc_frame.colorspace=ENC_CSP_UYVY; break;
    case IMGFMT_RGB24:
    case IMGFMT_BGR24:
    	vf->priv->enc_frame.colorspace=ENC_CSP_RGB24; break;
    default:
	mp_msg(MSGT_MENCODER,MSGL_ERR,"divx4: unsupported picture format (%s)!\n",
	    vo_format_name(outfmt));
	return 0;
    }

    switch(pass){
    case 1:
	if (VbrControl_init_2pass_vbr_analysis(passtmpfile, divx4_param.quality) == -1){
	    mp_msg(MSGT_MENCODER,MSGL_ERR,"2pass failed: filename=%s\n", passtmpfile);
	    pass=0;
	}
	break;
    case 2:
        if (VbrControl_init_2pass_vbr_encoding(passtmpfile,
					 divx4_param.bitrate,
					 divx4_param.framerate,
					 divx4_crispness,
					 divx4_param.quality) == -1){
	    mp_msg(MSGT_MENCODER,MSGL_ERR,"2pass failed: filename=%s\n", passtmpfile);
	    pass=0;
	}
	break;
    }

    return 1;
}

static int control(struct vf_instance_s* vf, int request, void* data){

    return CONTROL_UNKNOWN;
}

static int query_format(struct vf_instance_s* vf, unsigned int fmt){
    switch(fmt){
    case IMGFMT_YV12:
    case IMGFMT_IYUV:
    case IMGFMT_I420:
	return 3; // no conversion
    case IMGFMT_YUY2:
    case IMGFMT_UYVY:
	return 1; // conversion
    case IMGFMT_RGB24:
    case IMGFMT_BGR24:
	return 1 | VFCAP_FLIPPED; // conversion+flipped
    }
    return 0;
}

static void put_image(struct vf_instance_s* vf, mp_image_t *mpi){
    ENC_RESULT enc_result;
    vf->priv->enc_frame.image=mpi->planes[0];
    vf->priv->enc_frame.bitstream=mux_v->buffer;
    vf->priv->enc_frame.length=mux_v->buffer_size;
    vf->priv->enc_frame.mvs=NULL;
    if(pass==2){	// handle 2-pass:
    	vf->priv->enc_frame.quant = VbrControl_get_quant();
	vf->priv->enc_frame.intra = VbrControl_get_intra();
	encore(vf->priv->enc_handle,ENC_OPT_ENCODE_VBR,&vf->priv->enc_frame,&enc_result);
        VbrControl_update_2pass_vbr_encoding(enc_result.motion_bits,
					    enc_result.texture_bits,
					    enc_result.total_bits);
    } else {
	vf->priv->enc_frame.quant=0;
	vf->priv->enc_frame.intra=0;
	encore(vf->priv->enc_handle,ENC_OPT_ENCODE,&vf->priv->enc_frame,&enc_result);
	if(pass==1){
	  VbrControl_update_2pass_vbr_analysis(enc_result.is_key_frame, 
					       enc_result.motion_bits, 
					       enc_result.texture_bits, 
					       enc_result.total_bits, 
					       enc_result.quantizer);
	}
    }
    mencoder_write_chunk(mux_v,vf->priv->enc_frame.length,enc_result.is_key_frame?0x10:0);
}

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

static int vf_open(vf_instance_t *vf, char* args){
    vf->config=config;
    vf->control=control;
    vf->query_format=query_format;
    vf->put_image=put_image;
    vf->priv=malloc(sizeof(struct vf_priv_s));
    memset(vf->priv,0,sizeof(struct vf_priv_s));
    vf->priv->mux=(aviwrite_stream_t*)args;

    mux_v->bih=malloc(sizeof(BITMAPINFOHEADER));
    mux_v->bih->biSize=sizeof(BITMAPINFOHEADER);
    mux_v->bih->biWidth=0;
    mux_v->bih->biHeight=0;
    mux_v->bih->biPlanes=1;
    mux_v->bih->biBitCount=24;
#if ENCORE_MAJOR_VERSION >= 5010
    mux_v->bih->biCompression=mmioFOURCC('D','X','5','0');
#else
    mux_v->bih->biCompression=mmioFOURCC('d','i','v','x');
#endif

    return 1;
}

vf_info_t ve_info_divx4 = {
    "divx4 encoder",
    "divx4",
    "A'rpi",
    "for internal use by mencoder",
    vf_open
};

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