现在的位置: 首页 > 综合 > 正文

video 4 linux 2驱动的一种实现

2013年12月10日 ⁄ 综合 ⁄ 共 14070字 ⁄ 字号 评论关闭

Video for
linux 2驱动分为两层:
    VIDEO CORE LAYER(
videodev.
c)

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

    video heardward layer(
such as mxc_v4l2_capture.
c)

上一层文件是videodev.
c,这个文件其实就是相当于usbcore.
c文件一样,提供一些核心函数给下一层调用如video_register_device等,其实这个videodev.
c文件就是注册一个字符型设备,向操作系统提供file_operation这个结构体,而我们在video heardware layer里定义的一些函数就是通过file_operation里的一些指针来回调的。

camera_init:

    kmalloc一个cam_data对象g_cam,
调用init_camera_struct初始化该对象:
        init_camera_struct(
cam)
:

            初始化两个mutex-
-
param_lock和busy_lock,
然后调用video_device_alloc申请cam-
>
video_dev对象,然后将
                    static
struct
video_device mxc_v4l_template =
{

                        .
owner =
THIS_MODULE,

                        .
name =
"Mxc Camera"
,

                        .
type =
0,

                        .
type2 =
VID_TYPE_CAPTURE,

                        .
hardware =
0,

                        .
fops =
&
mxc_v4l_fops,

                        .
release =
video_device_release,

                    }
;

                    file_operations mxc_v4l_fops =
{

                        .
owner =
THIS_MODULE,

                        .
open
=
mxc_v4l_open,

                        .
release =
mxc_v4l_close,

                        .
read
=
mxc_v4l_read,

                        .
ioctl =
mxc_v4l_ioctl,

                        .
mmap =
mxc_mmap,

                        .
poll =
mxc_poll,

                    }
;

            赋值给cam-
>
video_dev对象,调用video_set_drvdata将cam设置成为cam-
>
video_dev的priv指向的对象,将cam-
>
driver_data指向
                static
struct
platform_device mxc_v4l2_devices =
{

                    .
name =
"mxc_v4l2"
,

                    .
dev =
{

                        .
release =
camera_platform_release,

                        }
,

                    .
id =
0,

                }
;

            中的.
dev。初始化cam-
>
frame[
3]
的width,
height及paddress。初始化两个等待队列cam-
>
enc_queue与cam-
>
still_queue,
然后初始化cropping,
standard,
streamparm,
overlay_on,
capture_on,
skip_frame,
v4l2fb,
v2f,
win.
然后是cam_sensor,即摄像头提供的一些调用函数(如白平衡等)。然后是enc_callback,将它指向camera_callback函数(该函数好像是有关工作队列的?????)。然后初始化cam-
>
power_queue队列,初始化cam-
>
int_lock自旋锁为未上锁。
        end init_camera_struct
    调用platform_device_register注册mxc_v4l2_devices对象,调用platform_driver_register注册
        static
struct
platform_driver mxc_v4l2_driver =
{

            .
driver =
{

                 .
name =
"mxc_v4l2"
,

                 .
owner =
THIS_MODULE,

                 .
bus =
&
platform_bus_type,

                 }
,

            .
probe =
NULL
,

            .
remove
=
NULL
,

            .
suspend =
mxc_v4l2_suspend,

            .
resume =
mxc_v4l2_resume,

            .
shutdown
=
NULL
,

        }
;

    对象,调用video_register_device(
cam-
>
video_dev,
VFL_TYPE_GRABBER,
video_nr)
注册一个视频设备在/
dev/
video0下,
end camera_init

static
int
mxc_v4l_open(
struct
inode *
inode,
struct
file
*
file
)
:

    先初始化dq_intr_cnt,
dq_timeout_cnt及empty_wq_cnt三个变量(估计与工作队列有关,???),调用mxc_get_video_input函数,其实就是调用cam-
>
cam_sensor-
>
get_status(
)
,也就是摄像头提供的函数。上busy_lock锁,调用signal_pending(
current)
判断当前是否有信号要处理。
    if是初次打开:调用wait_event_interruptible(其实在我们的系统中没有启动电源管理,所以cam-
>
low_power =
=
false应该一直都为真,也就是本函数都不会进入),然后调用prp_enc_select函数设置cam-
>
enc_update_eba指向prp_enc_update_eba,cam-
>
enc_enable指向prp_enc_enable,cam-
>
enc_disable指向prp_enc_disable。初始化cam-
>
enc_counter跟skip_frame,
初始化链表cam-
>
ready_q,cam-
>
working_q及cam-
>
done_q。使能IIC,调用param =
cam-
>
cam_sensor-
>
reset
(
)
,设置摄像头端的参数,返回摄像头初始化参数。根据返回的参数设置csi_param,然后调用csi_init_interface将参数设置入ARM端。调用cam-
>
cam_sensor-
>
get_color,cam-
>
cam_sensor-
>
get_ae_mode及cam-
>
cam_sensor-
>
get_control_params,最后调用prp_init,也就是申请INT_EMMAPRP中断,即函数prp_isr。释放busy_lock.

end mxc_v4l_open

mxc_v4l_do_ioctl:

    VIDIOC_QUERYCAP:

        查询能力
    end VIDIOC_QUERYCAP
        
    VIDIOC_G_FMT:
        调用mxc_v4l2_g_fmt(
cam,
gf)

        如果type是V4L2_BUF_TYPE_VIDEO_CAPTURE则返回cam-
>
v2f,
如果是V4L2_BUF_TYPE_VIDEO_OVERLAY则返回cam-
>
win.

    end VIDIOC_G_FMT
    
    VIDIOC_S_FMT:
        调用mxc_v4l2_s_fmt:
        如果是V4L2_BUF_TYPE_VIDEO_CAPTURE:
            这种情况下只支持两种格式-
-
V4L2_PIX_FMT_YUYV与V4L2_PIX_FMT_YUV420,但MX27的PRP通道2支持YUV444。然后将size,
bytesperline,
witdh,
height,
pixelformat设置入cam-
>
v2f中。
        如果是V4L2_BUF_TYPE_VIDEO_OVERLAY:
            检查参数,将f-
>
fmt.
win设置入cam-
>
win
    end VIDIOC_S_FMT
    
    VIDIOC_REQBUFS:

        要求传入来的req-
>
type要为V4L2_BUF_TYPE_VIDEO_CAPTURE,req-
>
memory要为V4L2_MEMORY_MMAP。然后调用cam-
>
enc_disable(
cam)
关闭PRP通道2,
置三个frame,cam-
>
frame[
i]
.
buffer.
flags =
V4L2_BUF_FLAG_MAPPED,初始化enc_counter,
skip_frame还有cam-
>
ready_q,cam-
>
working_q及cam-
>
done_q三个链表。
        调用mxc_free_frame_buf,即调用dma_free_coherent释放掉三个frame缓存(如果有的话)。
        调用mxc_allocate_frame_buf申请req-
>
count个buffer,
其中有一个ENABLE_DEINTERLACE_SCALE宏选项暂时不知道为什么要用???
        BUFFER的flag默认为V4L2_BUF_FLAG_MAPPED,type默认为V4L2_BUF_TYPE_VIDEO_CAPTURE,memory默认为V4L2_MEMORY_MMAP。
    end VIDIOC_REQBUFS
    
    VIDIOC_QUERYBUF:
        查询BUFFER的属性,即调用mxc_v4l2_buffer_status将cam-
>
frame[
buf-
>
index]
.
buffer考给用户。
    end VIDIOC_QUERYBUF
    
    VIDIOC_QBUF:
        好像是把一贞入cam-
>
working_q队列。
    end VIDIOC_QBUF
    
    VIDIOC_DQBUF
        未知
    end VIDIOC_DQBUF
    
    VIDIOC_STREAMON
        调用mxc_streamon
    end VIDIOC_STREAMON
    
    VIDIOC_STREAMOFF
        调用mxc_streamoff
    end VIDIOC_STREAMOFF
    
    VIDIOC_G_CTRL
        调用mxc_get_v42l_control并依据c-
>
id返回一些参数给用户
    end VIDIOC_G_CTRL
    
    VIDIOC_S_CTRL
        调用mxc_set_v42l_control设置摄像头参数,如白平衡等。
    end VIDIOC_S_CTRL
    
    VIDIOC_CROPCAP
        返回cam-
>
crop_bounds及cam-
>
crop_defrect给用户
    end VIDIOC_CROPCAP
    
    VIDIOC_G_CROP
        返回cam-
>
crop_current给用户
    end VIDIOC_G_CROP
end mxc_v4l_do_ioctl

Preview:
:
:
:
:

    1:先IOCTL传VIDIOC_S_OUTPUT命令设置输出,(其实按照实际情况还应该增加VIDIOC_G_STD命令获取CCD摄像头的类型为PAL还是NTSC,这样才能确定CSI端输入的是720*
576还是720*
487)
    2:再传VIDIOC_S_CROP命令设置剪裁的大小,注意传入的type为V4L2_BUF_TYPE_VIDEO_OVERLAY,传入驱动后赋值给cam-
>
crop_current
    3:再传入VIDIOC_S_FMT命令设置显示的大小,注意传入的type为V4L2_BUF_TYPE_VIDEO_OVERLAY,传入驱动后调用verify_preview()检查一下,然后赋值给cam-
>
win
    4:传入VIDIOC_S_FBUF命令设置cam-
>
v4l2_fb.
flags的值为V4L2_FBUF_FLAG_OVERLAY,这个值决定是用baselay还是overlay显示preview
    5:传入VIDIOC_OVERLAY开始preview,
调用start_preview()
    start_preview()
        调用prp_vf_select设置cam-
>
vf_start_sdc =
prp_vf_start和cam-
>
vf_stop_sdc =
prp_vf_stop两个函数指针。设置cam-
>
overlay_pid为当前进程ID,
调用prp_vf_start:
        prp_vf_start(
)

            如果cam-
>
v4l2_fb.
flags
的值为V4L2_FBUF_FLAG_OVERLAY,即如果是要在overlay里显示,那么调用prp_vf_mem_alloc申请两块dma缓存
给LOOP模式缓冲帧数据,prp支持旋转,如果有图像旋转的需要的话就调用prp_rot_mem_alloc申请缓冲(没具体分析)。
            调用prp_v4l2_cfg(
&
g_prp_cfg,
cam)
设置prp的各项参数,这里设置了很多PRP的参数,包括LOOP缓冲区的地址,CH1和CH2的图像格式(YUV,RGB),工作模式及根据IN和OUT算得的缩放参数等等,这里只是将这些参数写入全局变量g_prp_cfg中。
                prp_v4l2_cfg()
                    设置PRP通道的输入参数,当然先是设置在g_prp_cfg中,包括宽,高, line
stride,
skip line,还有是否LOOP双缓冲;下面如果是overlay显示的话,通过查询cam-
>
v4l2_fb.
fmt.
pixelformat变量获得显示的格式(这个参数在系统设计时通过VIDIOC_S_FBUF命令设置,但我们的APP当中OVERLAY preview的时候并没有设置该参数,所以它应该CASE到DEFAULT,
也就是PRP_PIX1_RGB565);下面设置channel1的输出宽跟高(即为cam-
>
win.
w.
width与cam-
>
win.
w.
height),调用set_ch1_addr设置通道1的两个缓冲区地址,也就是前面prp_vf_mem_alloc所申请的。
                end prp_v4l2_cfg(
)

            调用csi_enable_mclk(
)
设置CSI模块的时钟,调用prphw_reset复位prp模块,然后调用prphw_cfg()将刚才配置的各个PRP参数g_prp_cfg设置入寄存器。
            调用tasklet_init(
&
prp_vf_tasklet,
rotation,
(
unsigned
long
)
private
)
;
启动一个tasklet,
这个是用作图像旋转的。
        end prp_vf_start(
)

    end start_preview

end Preview

capture:
:
:
:
:
:
:

    通过VIDIOC_S_FMT命令,设置fmt,即包括type为V4L2_BUF_TYPE_VIDEO_CAPTURE,数据格式为V4L2_PIX_FMT_YUV420,还有输出的画面大小。
    在mxc_v4l2_s_fmt函数中:
        mxc_v4l2_s_fmt()
            当fmt.
type为V4L2_BUF_TYPE_VIDEO_CAPTURE时,下面根据fmt.
pix.
pixelformat类型来设置size,取圆整fmt.
pix.
width与fmt.
pix.
hight,最后将fmt设置入cam-
>
v2f.
fmt中。
        end mxc_v4l2_s_fmt(
)

    通过VIDIOC_S_PARM命令,设置v4l2_streamparm,即包括V4L2_BUF_TYPE_VIDEO_CAPTURE,还有帧率,传入内核中时:
        mxc_v4l2_s_param()
            如果parm-
>
type不为V4L2_BUF_TYPE_VIDEO_CAPTURE,则出错返回。接下来检查传入的帧率是否支持,然后判断parm.
capture.
capturemode是否改变,即是否要改变摄像头输入的分辨率,如果要改变的放就再一次调用cam_sensor-
>
config及csi_init_interface重新初始化摄像头及CSI模块。
        end mxc_v4l2_s_param(
)

    通
过VIDIOC_REQBUFS命令,设置v4l2_requestbuffers,即包括type
为V4L2_BUF_TYPE_VIDEO_CAPTURE,buffer数量(驱动中最大支持3个缓冲)及抓取方式为
V4L2_MEMORY_MMAP,在我们的系统驱动中只支持V4L2_MEMORY_MMAP方式,调用mxc_streamoff及
mxc_free_frame_buf确保当前各模块为空闲状态,最后调用mxc_allocate_frame_buf申请cnt个缓冲数量(不能超过
3个),并设置flag为V4L2_BUF_FLAG_MAPPED方式。
    通过VIDIOC_QUERYBUF命令,获取v4l2_buffer参数,包括缓冲的length及offset,
然后APP中调用mmap函数将内核的缓冲映射到用户空间。注意这个命令调用cnt次,也即是映射最多3个缓冲。
    通过VIDIOC_QBUF命令,将这些帧缓冲区(最多3个)插入驱动的队列。。。驱动中:如果cam-
>
overflow为1,
(????),然后调用spin_lock_irqsave上锁cam-
>
int_lock,接下下判断buffer的flags,为V4L2_BUF_FLAG_MAPPED的话,这时判断是否skip_frame,然后调用list_add_tail(
&
cam-
>
frame[
index]
.
queue
,
&
cam-
>
ready_q)
将其插入ready_q队列。最后调用spin_lock_irqsave解锁。
    通过VIDIOC_STREAMON命令,让驱动开始抓取数据。。。。驱动中:
        mxc_streamon()
            调用list_empty(
&
cam-
>
ready_q)
判断ready_q是否为空,如果为空,返回 。设置cam-
>
capture_pid为当前进程ID,调用cam-
>
enc_enable回调,即prp_enc_enable
                调用prp_v4l2_cfg设置PRP参数,调用csi_enable_mclk使能csi的时钟,prphw_reset,复位PRP,
调用prphw_cfg将参数设置入寄存器,调用prphw_enable使能PRP通道。
            接下来设置cam-
>
ping_pong_csi为0(???),在cam-
>
ready_q中取出一帧,然后将它从ready_q中删除,接着将它插入cam-
>
working_q中,然后调用cam-
>
enc_update_eba回调函数即prp_enc_update_eba:
                prp_enc_update_eba()
                    该函数更新g_prp_cfg.
ch2_ptr2,
即是将通道2的地址设置为帧的起始地址,然后还有一个变量是buffer_num,看程序好像是在0与1之间切换,第一次传入来时为0,
然后将它设置为1。
                end prp_enc_update_eba(
)

             接下来再同样从cam-
>
ready_q中取出一帧 ,插入wrking_q中,也调用prp_enc_update_ebq。
        end mxc_streamon(
)

    通过VIDIOC_DQBUF命令,让驱动将帧队列出队,驱动中:
        mxc_v4l_dqueue()
            函数开始就调用wait_event_interruptible_timeout(
cam-
>
enc_queue,
cam-
>
enc_counter !
=
0,
10 *
HZ)
,将该进程等待在cam-
>
enc_queue队列上,而这个队列是在prp的中断处理函数中调用camera_callback函数,有一行wake_up_interruptible(
&
cam-
>
enc_queue)
,它唤醒了mxc_v4l_dqueue函数。我们还是回来看下该函数,当超时的时候,(????)或者有信号中断来了(???好像跟超时的处理一样),接下来判断是否cam-
>
overflow(???这时候的处理跟上面一样?)
            下面就是正常情况下的处理了,先cam-
>
enc_counter-
-
,上spin_lock_irqsave锁cam-
>
int_lock,在cam-
>
done_q队列中取出一帧,并将这一帧从done_q队列中删除。解锁spin_unlock_irqrestore。然后判断这帧的buffer.
flags,如果它被置为V4L2_BUF_FLAG_DONE,清除V4L2_BUF_FLAG_DONE,其它情况均返回出错。接下来如果要de-
interlace的话,就根据YUV420格式来memcpy,最后设置该帧缓冲的属性,如帧大小,FALGS,还有timestamp等等。
        end mxc_v4l_dqueue(
)

end capture

prp_isr(
)
这个是PRP中断处理函数,系统设置是当一个帧传输完的时候会触发一个中断。
    函数先调用prphw_isr读取中断的状态,并根据状态标志位打印一些错误,然后清除中断位,返回中断状态。接下来分几种情况处理,分别为-
-
拍照片时,预览时,录像时这三种。
    当为录像时,判断该中断是否为buffer1或buffer2所触发的,如果是,则调用cam-
>
enc_callback(
0,
cam)
回调,即是static void
camera_callback(
u32 mask,
void
*
dev)

        camera_callback()
            传入的mask为是否overflow的标志,如果它为1,
则将cam-
>
overflow置为1,
下面用spin_lock_irqsave锁cam-
>
int_lock,接下来判断cam-
>
working_q是否为空,前面我们已经将APP里的帧插入到这人working_q中,所以这里为空的话应该是不正常的情况,如果为空的话,先判断全局变量empty_wq_cnt,如果为0,
则打印working queue为空错误,下面将该变量自加,下来判断cam-
>
ready_q是否为空,如果为空的话,cam-
>
skip_frame自加,也即跳过该帧,否则的话将ready_q中出队一帧,插入working_q中,并调用cam-
>
enc_update_eba(
ready_frame-
>
paddress,
&
cam-
>
ping_pong_csi)
;
更新帧的地址。解锁cam-
>
int_lock,返回。。
            接
下来是正常情况的处理,也即是working_q不为空的情况,这时在该队列中取出一帧,如果该帧的falgs有
V4L2_BUF_FLAG_QUEUED标志的话,清除该标志,并置上V4L2_BUF_FLAG_DONE位。下面同样是判断ready_q是否有帧
在排队,有的话插入working_q队列,再下面是将该帧从working_q出队,因为它已经被prp模块填满数据了,将它插入cam-
>
done_q队列。将cam-
>
enc_counter自加,然后调用wake_up_interruptible(
&
cam-
>
enc_queue)
;
唤醒等待在cam-
>
enc_queue队列的进程。最后do_gettimeofday,将该帧打上时间戳。调用spin_unlock_irqrestore解锁cam-
>
int_lock
        end camera_callback(
)

end prp_isr(
)

typedef
struct
_cam_data {

    struct
video_device *
video_dev;

    /* semaphore guard against SMP multithreading */

    struct
semaphore busy_lock;

    int
open_count;

    /* params lock for this camera */

    struct
semaphore param_lock;

    /* Encorder */

    struct
list_head ready_q;

    struct
list_head done_q;

    struct
list_head working_q;

    int
ping_pong_csi;

    spinlock_t int_lock;

    struct
mxc_v4l_frame frame[
FRAME_NUM]
;

    int
skip_frame;

    int
overflow;

    wait_queue_head_t enc_queue;

    int
enc_counter;

    dma_addr_t rot_enc_bufs[
2]
;

    void
*
rot_enc_bufs_vaddr[
2]
;

    int
rot_enc_buf_size[
2]
;

    enum
v4l2_buf_type type;

    /* still image capture */

    wait_queue_head_t still_queue;

    int
still_counter;

    dma_addr_t still_buf;

    void
*
still_buf_vaddr;

    /* overlay */

    struct
v4l2_window win;

    struct
v4l2_framebuffer v4l2_fb;

    dma_addr_t vf_bufs[
2]
;

    void
*
vf_bufs_vaddr[
2]
;

    int
vf_bufs_size[
2]
;

    dma_addr_t rot_vf_bufs[
2]
;

    void
*
rot_vf_bufs_vaddr[
2]
;

    int
rot_vf_buf_size[
2]
;

    bool
overlay_active;

    int
output;

    struct
fb_info *
overlay_fb;

    /* v4l2 format */

    struct
v4l2_format v2f;

    int
rotation;

    struct
v4l2_mxc_offset offset;

    /* V4l2 control bit */

    int
bright;

    int
hue;

    int
contrast;

    int
saturation;

    int
red;

    int
green;

    int
blue;

    int
ae_mode;

    int
ae_enable;

    int
awb_enable;

    int
flicker_ctrl;

    /* standart */

    struct
v4l2_streamparm streamparm;

    struct
v4l2_standard standard;

    /* crop */

    struct
v4l2_rect crop_bounds;

    struct
v4l2_rect crop_defrect;

    struct
v4l2_rect crop_current;

    int
(
*
enc_update_eba)
(
dma_addr_t eba,
int
*
bufferNum)
;

    int
(
*
enc_enable)
(
void
*
private
)
;

    int
(
*
enc_disable)
(
void
*
private
)
;

    void
(
*
enc_callback)
(
u32 mask,
void
*
dev)
;

    int
(
*
vf_start_adc)
(
void
*
private
)
;

    int
(
*
vf_stop_adc)
(
void
*
private
)
;

    int
(
*
vf_start_sdc)
(
void
*
private
)
;

    int
(
*
vf_stop_sdc)
(
void
*
private
)
;

    int
(
*
csi_start)
(
void
*
private
)
;

    int
(
*
csi_stop)
(
void
*
private
)
;

    /* misc status flag */

    bool
overlay_on;

    bool
capture_on;

    int
overlay_pid;

    int
capture_pid;

    bool
low_power;

    wait_queue_head_t power_queue;

    /* camera sensor interface */

    struct
camera_sensor *
cam_sensor;

}
cam_data;

另外附上PAL与NTSC制式的区别:
很多人都知道有NTSC和PAL两大制式,那到底什么是NTSC制式?什么是PAL制式呢?简单的说,NTSC和PAL属于全球两大主要的电视广播制式,但是由于系统投射颜色影像的频率而有所不同。NTSC是National Television System
Committee的缩写,其标准主要应用于日本、美国,加拿大、墨西哥等等,PAL 则是Phase Alternating Line的缩写,主要应用于中国,香港、中东地区和欧洲一带。

    这
两种制式是不能互相兼容的,如果在PAL制式的电视上播放NTSC的影响,画面将变成黑白,NTSC制式的也是一样。而做为视频拍摄工具的数码摄像机,也
同样有制式的问题,比如我国使用PAL制式,在我国销售的数码摄像机都是PAL制式的,如果是NTSC制式的摄像机拍摄出来的图象不能在PAL制式的电视
机上正常播放。因此,可以肯定的说,在我国销售的数码摄像机行货一定是PAL制式的,如果是NTSC制式的数码摄像机,则一定是水货。

    PAL制式和NTSC的分辨率也有所不同,PAL制式使用的是720*
576,而NTSC制式使用的是760*
480,在分辨率上PAL稍稍占有优势。而PAL制式的画面解析度720*
576,约40万象素,也决定了PAL制式的数码摄像机的CCD大小应该为40万的倍数或者半倍数,比如2倍或者1.
5倍,所以PAL制式数码摄像机都是80万,或者107万(接近100万,40万的2.
5倍)、155万(接近160万,40万的4倍)。而NTSC制式的画面解析度为720*
480,约34万象素,所以NTSC制式的数码摄像机一般为68万象素等等。

    目前的视频采集软件都支持PAL和NTSC制式,但是在编辑过程中是不能同时使用NTSC制式的素材和PAL制式的素材,必须用过转换才能在同一时间轴上使用两个素材。

 
在PC领域,由于使用的制式不同,存在不兼容的情况。就拿分辨率来说,有的制式每帧有625线(50Hz),有的则每帧只有525线(60
Hz)。后者是北美和日本采用的标准,统称为NTSC。通常,一个视频信号是由一个视频源生成的,比如摄像机、VCR或者电视调谐器等。为传输图像,视频
源首先要生成-
个垂直同步信号(V
SYNC)。这个信号会重设接收端设备(PC显示器),保征新图像从屏幕的顶部开始显示。发出VSYNC信号之后,视频源接着扫描图像的第一行。完成后,
视频源又生成一个水平同步信号,重设接收端,以便从屏幕左侧开始显示下一行。并针对图像的每一行,都要发出一条扫描线,以及一个水平同步脉冲信号。

  另外,NTSC标准还规定视频源每秒钟需要发送30幅完整的图像(帧)。假如不作其它处理,闪烁现象会非常严重。为解决这个问题,每帧又被均分为两部分,每部分2 62.
5行。一部分全是奇数行,另一部分则全是偶数行。显示的时候,先扫描奇数行,再扫描偶数行,就可以有效地改善图像显示的稳定性,减少闪烁。目前世界上彩色电视主要有三种制式,即N TSC、PAL和SECAM制式,三种制式目前尚无法统一。

抱歉!评论已关闭.