📄 cx88-blackbird.c
字号:
/* assign bitrates */ if( params->vi_bitrate.mode ) { /* bitrate is set, let's figure out the cbr/vbr mess */ if( params->vi_bitrate.max < params->vi_bitrate.target ) { if( params->vi_bitrate.mode == V4L2_BITRATE_CBR ) params->vi_bitrate.max = params->vi_bitrate.target; else params->vi_bitrate.target = params->vi_bitrate.max; } } else { if( params->st_bitrate.max < params->st_bitrate.target ) { if( params->st_bitrate.mode == V4L2_BITRATE_VBR ) params->st_bitrate.target = params->st_bitrate.max; else params->st_bitrate.max = params->st_bitrate.target; } /* calculate vi_bitrate = st_bitrate - au_bitrate */ params->vi_bitrate.max = params->st_bitrate.max - params->au_bitrate.max; params->vi_bitrate.target = params->st_bitrate.target - params->au_bitrate.target; } blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 4, 0, mpeg_video_bitrates[params->vi_bitrate.mode], params->vi_bitrate.target * 1000, /* kbps -> bps */ params->vi_bitrate.max * 1000 / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */ BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */ /* TODO: implement the stream ID stuff: ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr, ps_size, au_pesid, vi_pesid */}#define CHECK_PARAM( name ) ( dev->params.name != params->name )#define IF_PARAM( name ) if( CHECK_PARAM( name ) )#define UPDATE_PARAM( name ) dev->params.name = params->namevoid blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression *params){ u32 au_params; /* assign stream type */ if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) ) params->st_type = V4L2_MPEG_PS_2; if( params->st_type == V4L2_MPEG_SS_1 ) params->vi_type = V4L2_MPEG_VI_1; else params->vi_type = V4L2_MPEG_VI_2; if( CHECK_PARAM( st_type ) || CHECK_PARAM( vi_type ) ) { UPDATE_PARAM( st_type ); UPDATE_PARAM( vi_type ); blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, mpeg_stream_types[params->st_type]); } /* assign framerate */ if( params->vi_frame_rate <= 25 ) params->vi_frame_rate = 25; else params->vi_frame_rate = 30; IF_PARAM( vi_frame_rate ) { UPDATE_PARAM( vi_frame_rate ); if( params->vi_frame_rate == 25 ) blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25); else blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_NTSC_30); } /* assign aspect ratio */ if( params->vi_aspect_ratio >= ARRAY_SIZE(mpeg_stream_ratios) ) params->vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3; IF_PARAM( vi_aspect_ratio ) { UPDATE_PARAM( vi_aspect_ratio ); blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, mpeg_stream_ratios[params->vi_aspect_ratio]); } /* assign gop properties */ if( CHECK_PARAM( vi_frames_per_gop ) || CHECK_PARAM( vi_bframes_count ) ) { UPDATE_PARAM( vi_frames_per_gop ); UPDATE_PARAM( vi_bframes_count ); blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, params->vi_frames_per_gop, params->vi_bframes_count+1); } /* assign gop closure */ IF_PARAM( closed_gops ) { UPDATE_PARAM( closed_gops ); blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, params->closed_gops); } /* assign 3 2 pulldown */ IF_PARAM( pulldown ) { UPDATE_PARAM( pulldown ); blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, params->pulldown); } /* make sure the params are within bounds */ if( params->st_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) params->vi_bitrate.mode = V4L2_BITRATE_NONE; if( params->vi_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) params->vi_bitrate.mode = V4L2_BITRATE_NONE; if( params->au_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) params->au_bitrate.mode = V4L2_BITRATE_NONE; /* assign audio properties */ /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */ au_params = BLACKBIRD_AUDIO_BITS_STEREO | /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */ BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE | BLACKBIRD_AUDIO_BITS_CRC_OFF | BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF | BLACKBIRD_AUDIO_BITS_COPY | 0; if( params->au_sample_rate < 32000 ) { params->au_sample_rate = 32000; au_params |= BLACKBIRD_AUDIO_BITS_32000HZ; } else if( params->au_sample_rate < 44100 ) { params->au_sample_rate = 44100; au_params |= BLACKBIRD_AUDIO_BITS_44100HZ; } else { params->au_sample_rate = 48000; au_params |= BLACKBIRD_AUDIO_BITS_48000HZ; } if( params->au_type == V4L2_MPEG_AU_2_I ) { au_params |= BLACKBIRD_AUDIO_BITS_LAYER_1; } else { /* TODO: try to handle the other formats more gracefully */ params->au_type = V4L2_MPEG_AU_2_II; au_params |= BLACKBIRD_AUDIO_BITS_LAYER_2; } if( params->au_bitrate.mode ) { int layer; if( params->au_bitrate.mode == V4L2_BITRATE_CBR ) params->au_bitrate.max = params->vi_bitrate.target; else params->au_bitrate.target = params->vi_bitrate.max; layer = params->au_type; if( params->au_bitrate.target == 0 ) { /* TODO: use the minimum possible bitrate instead of 0 ? */ au_params |= 0; } else if( params->au_bitrate.target >= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) { /* clamp the bitrate to the max supported by the standard */ params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate; params->au_bitrate.max = params->au_bitrate.target; au_params |= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].bits; } else { /* round up to the nearest supported bitrate */ int i; for(i = 1; i < BITRATES_SIZE; i++) { if( params->au_bitrate.target > mpeg_audio_bitrates[i-1].layer[layer].rate && params->au_bitrate.target <= mpeg_audio_bitrates[i].layer[layer].rate ) { params->au_bitrate.target = mpeg_audio_bitrates[i].layer[layer].rate; params->au_bitrate.max = params->au_bitrate.target; au_params |= mpeg_audio_bitrates[i].layer[layer].bits; break; } } } } else { /* TODO: ??? */ params->au_bitrate.target = params->au_bitrate.max = 0; au_params |= 0; } if( CHECK_PARAM( au_type ) || CHECK_PARAM( au_sample_rate ) || CHECK_PARAM( au_bitrate.mode ) || CHECK_PARAM( au_bitrate.max ) || CHECK_PARAM( au_bitrate.target ) ) { UPDATE_PARAM( au_type ); UPDATE_PARAM( au_sample_rate ); UPDATE_PARAM( au_bitrate ); blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0, au_params ); } /* assign bitrates */ if( params->vi_bitrate.mode ) { /* bitrate is set, let's figure out the cbr/vbr mess */ if( params->vi_bitrate.max < params->vi_bitrate.target ) { if( params->vi_bitrate.mode == V4L2_BITRATE_CBR ) params->vi_bitrate.max = params->vi_bitrate.target; else params->vi_bitrate.target = params->vi_bitrate.max; } } else { if( params->st_bitrate.max < params->st_bitrate.target ) { if( params->st_bitrate.mode == V4L2_BITRATE_VBR ) params->st_bitrate.target = params->st_bitrate.max; else params->st_bitrate.max = params->st_bitrate.target; } /* calculate vi_bitrate = st_bitrate - au_bitrate */ params->vi_bitrate.max = params->st_bitrate.max - params->au_bitrate.max; params->vi_bitrate.target = params->st_bitrate.target - params->au_bitrate.target; } UPDATE_PARAM( st_bitrate ); if( CHECK_PARAM( vi_bitrate.mode ) || CHECK_PARAM( vi_bitrate.max ) || CHECK_PARAM( vi_bitrate.target ) ) { UPDATE_PARAM( vi_bitrate ); blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 4, 0, mpeg_video_bitrates[params->vi_bitrate.mode], params->vi_bitrate.target * 1000, /* kbps -> bps */ params->vi_bitrate.max * 1000 / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */ BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */ } /* TODO: implement the stream ID stuff: ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr, ps_size, au_pesid, vi_pesid */ UPDATE_PARAM( ts_pid_pmt ); UPDATE_PARAM( ts_pid_audio ); UPDATE_PARAM( ts_pid_video ); UPDATE_PARAM( ts_pid_pcr ); UPDATE_PARAM( ps_size ); UPDATE_PARAM( au_pesid ); UPDATE_PARAM( vi_pesid );}static void blackbird_set_default_dnr_params(struct cx8802_dev *dev){ /* assign dnr filter mode */ if( dev->dnr_params.mode > BLACKBIRD_DNR_BITS_AUTO ) dev->dnr_params.mode = BLACKBIRD_DNR_BITS_MANUAL; if( dev->dnr_params.type > BLACKBIRD_MEDIAN_FILTER_DIAGONAL ) dev->dnr_params.type = BLACKBIRD_MEDIAN_FILTER_DISABLED; blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0, dev->dnr_params.mode, dev->dnr_params.type ); /* assign dnr filter props*/ if( dev->dnr_params.spatial > 15 ) dev->dnr_params.spatial = 15; if( dev->dnr_params.temporal > 31 ) dev->dnr_params.temporal = 31; blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, dev->dnr_params.spatial, dev->dnr_params.temporal );}#define CHECK_DNR_PARAM( name ) ( dev->dnr_params.name != dnr_params->name )#define UPDATE_DNR_PARAM( name ) dev->dnr_params.name = dnr_params->namevoid blackbird_set_dnr_params(struct cx8802_dev *dev, struct blackbird_dnr* dnr_params){ /* assign dnr filter mode */ /* clamp values */ if( dnr_params->mode > BLACKBIRD_DNR_BITS_AUTO ) dnr_params->mode = BLACKBIRD_DNR_BITS_MANUAL; if( dnr_params->type > BLACKBIRD_MEDIAN_FILTER_DIAGONAL ) dnr_params->type = BLACKBIRD_MEDIAN_FILTER_DISABLED; /* check if the params actually changed */ if( CHECK_DNR_PARAM( mode ) || CHECK_DNR_PARAM( type ) ) { UPDATE_DNR_PARAM( mode ); UPDATE_DNR_PARAM( type ); blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0, dnr_params->mode, dnr_params->type); } /* assign dnr filter props*/ if( dnr_params->spatial > 15 ) dnr_params->spatial = 15; if( dnr_params->temporal > 31 ) dnr_params->temporal = 31; if( CHECK_DNR_PARAM( spatial ) || CHECK_DNR_PARAM( temporal ) ) { UPDATE_DNR_PARAM( spatial ); UPDATE_DNR_PARAM( temporal ); blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, dnr_params->spatial, dnr_params->temporal); }}static void blackbird_codec_settings(struct cx8802_dev *dev){ /* assign output port */ blackbird_api_cmd(dev, BLACKBIRD_API_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */ /* assign frame size */ blackbird_api_cmd(dev, BLACKBIRD_API_SET_RESOLUTION, 2, 0, dev->height, dev->width); /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */ blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MEDIAN, 4, 0, 0, 255, 0, 255); /* assign spatial filter type: luma_t: horiz_only, chroma_t: horiz_only */ blackbird_api_cmd(dev, BLACKBIRD_API_SET_SPATIAL_FILTER, 2, 0, BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ, BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ ); /* assign frame drop rate */ /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); */ blackbird_set_default_params(dev); blackbird_set_default_dnr_params(dev);}static int blackbird_initialize_codec(struct cx8802_dev *dev){ struct cx88_core *core = dev->core; int version; int retval; dprintk(1,"Initialize codec\n"); retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */ if (retval < 0) { /* ping was not successful, reset and upload firmware */ cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ msleep(1); cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */ msleep(1); retval = blackbird_load_firmware(dev); if (retval < 0) return retval; dev->mailbox = blackbird_find_mailbox(dev); if (dev->mailbox < 0) return -1; retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */ if (retval < 0) { dprintk(0, "ERROR: Firmware ping failed!\n"); return -1; } retval = blackbird_api_cmd(dev, BLACKBIRD_API_GET_VERSION, 0, 1, &version); if (retval < 0) { dprintk(0, "ERROR: Firmware get encoder version failed!\n"); return -1; } dprintk(0, "Firmware version is 0x%08x\n", version); } msleep(1); cx_write(MO_PINMUX_IO, 0x88); /* 656-8bit IO and enable MPEG parallel IO */ cx_clear(MO_INPUT_FORMAT, 0x100); /* chroma subcarrier lock to normal? */ cx_write(MO_VBOS_CONTROL, 0x84A00); /* no 656 mode, 8-bit pixels, disable VBI */ cx_clear(MO_OUTPUT_FORMAT, 0x0008); /* Normal Y-limits to let the mpeg encoder sync */ blackbird_codec_settings(dev); msleep(1); /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef); blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0); blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); */ blackbird_api_cmd(dev, BLACKBIRD_API_SET_CAPTURE_LINES, 2, 0, BLACKBIRD_FIELD1_SAA7115, BLACKBIRD_FIELD2_SAA7115 ); /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); */ blackbird_api_cmd(dev, BLACKBIRD_API_SET_CUSTOM_DATA, 12, 0, BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); /* initialize the video input */ blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0); msleep(1); blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE); msleep(1); blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE); msleep(1); /* start capturing to the host interface */ /* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); */ blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, BLACKBIRD_MPEG_CAPTURE, BLACKBIRD_RAW_BITS_NONE ); msleep(10); blackbird_api_cmd(dev, BLACKBIRD_API_REFRESH_INPUT, 0,0); return 0;}/* ------------------------------------------------------------------ */static int bb_buf_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size){ struct cx8802_fh *fh = q->priv_data; fh->dev->ts_packet_size = 188 * 4; /* was: 512 */ fh->dev->ts_packet_count = mpegbufs; /* was: 100 */ *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count; *count = fh->dev->ts_packet_count;#if 0 if (0 == *count) *count = mpegbufs; if (*count < 2) *count = 2; if (*count > 32) *count = 32;#endif return 0;}static intbb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field){ struct cx8802_fh *fh = q->priv_data; return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field);}static voidbb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb){ struct cx8802_fh *fh = q->priv_data; cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb);}static voidbb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb){ cx88_free_buffer(q, (struct cx88_buffer*)vb);}static struct videobuf_queue_ops blackbird_qops = { .buf_setup = bb_buf_setup, .buf_prepare = bb_buf_prepare, .buf_queue = bb_buf_queue, .buf_release = bb_buf_release,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -