网络摄像头2 mjpg_streamer流程,编译

refer to
http://www.friendlyarm.net/forum/topic/279?lang=en
http://code.google.com/p/mjpg-streamer-mini2440/
http://code.google.com/p/mjpg-streamer-mini2440/source/checkout

下载mjpg_streamer源码并观察源码结构如下
[root@localhost tmp]# svn checkout http://mjpg-streamer-mini2440.googlecode.com/svn/trunk/ mjpg-streamer-mini2440-read-only
[root@localhost tmp]# cd mjpg-streamer-mini2440-read-only/
[root@localhost mjpg-streamer-mini2440-read-only]# pwd
/tmp/mjpg-streamer-mini2440-read-only

[root@localhost mjpg-streamer-mini2440-read-only]# tree
.
|-- CHANGELOG
|-- LICENSE
|-- Makefile
|-- README
|-- mjpg-streamer-mini2440.kdev4
|-- mjpg_streamer.c
|-- mjpg_streamer.h
|-- plugins
|   |-- input.h
|   |-- input_control
|   |   |-- Makefile
|   |   |-- dynctrl.c
|   |   |-- dynctrl.h
|   |   |-- input_uvc.c
|   |   |-- uvc_compat.h
|   |   `-- uvcvideo.h
|   |-- input_file
|   |   |-- Makefile
|   |   `-- input_file.c
|   |-- input_gspcav1
|   |   |-- Makefile
|   |   |-- encoder.c
|   |   |-- encoder.h
|   |   |-- huffman.c
|   |   |-- huffman.h
|   |   |-- input_gspcav1.c
|   |   |-- jconfig.h
|   |   |-- jdatatype.h
|   |   |-- marker.c
|   |   |-- marker.h
|   |   |-- quant.c
|   |   |-- quant.h
|   |   |-- readme.spcacat
|   |   |-- spcaframe.h
|   |   |-- spcav4l.c
|   |   |-- spcav4l.h
|   |   |-- utils.c
|   |   `-- utils.h
|   |-- input_s3c2410
|   |   |-- Makefile
|   |   |-- input_s3c2410.c
|   |   |-- readme.s3c2410
|   |   |-- s3c2410.c
|   |   |-- s3c2410.h
|   |   |-- utils.c
|   |   `-- utils.h
|   |-- input_testpicture
|   |   |-- Makefile
|   |   |-- input_testpicture.c
|   |   |-- pictures
|   |   |   |-- 160x120_1.jpg
|   |   |   |-- 160x120_2.jpg
|   |   |   |-- 320x240_1.jpg
|   |   |   |-- 320x240_2.jpg
|   |   |   |-- 640x480_1.jpg
|   |   |   |-- 640x480_2.jpg
|   |   |   |-- 960x720_1.jpg
|   |   |   `-- 960x720_2.jpg
|   |   `-- testpictures.h
|   |-- input_uvc
|   |   |-- Makefile
|   |   |-- dynctrl.c
|   |   |-- dynctrl.h
|   |   |-- huffman.h
|   |   |-- input_uvc.c
|   |   |-- jpeg_utils.c
|   |   |-- jpeg_utils.h
|   |   |-- uvc_compat.h
|   |   |-- uvcvideo.h
|   |   |-- v4l2uvc.c
|   |   `-- v4l2uvc.h
|   |-- output.h
|   |-- output_autofocus
|   |   |-- Makefile
|   |   |-- output_autofocus.c
|   |   |-- processJPEG_onlyCenter.c
|   |   `-- processJPEG_onlyCenter.h
|   |-- output_file
|   |   |-- Makefile
|   |   `-- output_file.c
|   `-- output_http
|       |-- Makefile
|       |-- httpd.c
|       |-- httpd.h
|       `-- output_http.c
|-- simplified_jpeg_encoder.c
|-- simplified_jpeg_encoder.h
|-- start_s3c2410.sh
|-- start_uvc.sh
|-- start_uvc_yuv.sh
|-- utils.c
|-- utils.h
`-- www
    |-- LICENSE.txt
    |-- bodybg.gif
    |-- cambozola.jar
    |-- control.htm
    |-- example.jpg
    |-- favicon.ico
    |-- favicon.png
    |-- fix.css
    |-- functions.js
    |-- index.html
    |-- java.html
    |-- java_control.html
    |-- java_simple.html
    |-- javascript.html
    |-- javascript_motiondetection.html
    |-- javascript_simple.html
    |-- sidebarbg.gif
    |-- static.html
    |-- static_simple.html
    |-- stream.html
    |-- stream_simple.html
    |-- style.css
    `-- videolan.html

12 directories, 104 files
[root@localhost mjpg-streamer-mini2440-read-only]# 


其中
主目录下
|-- start_s3c2410.sh
|-- start_uvc.sh
|-- start_uvc_yuv.sh
这几个脚本用于执行mjpg_streamer并传递参数给main
|-- simplified_jpeg_encoder.c
|-- simplified_jpeg_encoder.h
用于对input模块从驱动中取得图像的数据进行编码
mjpg_streamer.h,定义了一个重要的全局结构体globals
mjpg_streamer.c,main函数所在文件,此文件分析启动命令并初始化,并定义静态全局变量 static globals global;

plugins/目录下是一些插件,以so文件形式提供,在装载时动态链接。其中
plugins/input_file
plugins/input_gspcav1
plugins/input_s3c2410目录,读取cmos摄像头驱动中的数据,保存到全局变量global
plugins/input_testpicture
plugins/input_uvc目录,读取usb摄像头驱动中的数据,保存到全局变量global
plugins/output_autofocus
plugins/output_file目录,用于将图像数据保存到文件
plugins/output_http目录,用于监视外部端口(默认8080)的socket请求,将图像数据通过socket发出。即是一个小型web服务器,支持同时发起的xx个链接。


www目录下是几个网页

**************************************************************************************************************************************************************

对源码试着编译一下---在板子上先插入cmos摄像头,型号0v9650

先修改mjpg_streamer.h,添加DEBUG宏,以便出错时可以知道错在哪里
#define DEBUG
再修改Makefile,指定编译器,并指定生成input_s3c2410.so插件
CC = arm-linux-gcc
PLUGINS += input_s3c2410.so
执行
make
make package
此时会生成mjpg-streamer-mini2440-bin.tar.gz,考到板子上解压后进入它的目录

执行
./start_s3c2410.sh
结果如下

MJPG Streamer Version.: 2.0
 DBG(input_s3c2410.c, input_init(), 95): argv[0]=S3C2410 embedded camera
 DBG(input_s3c2410.c, input_init(), 169): initializing s3c2410 device
 i: Using V4L2 device.: /dev/video0
 i: Desired Resolution: 640 x 512
 i: Grayscale mode: off
 DBG(s3c2410.c, init_s3c2410(), 63): Opening device
ERROR opening V4L interface
即打开video0时出现问题,修改start_s3c2410.sh ,在-i参数里指定设备文件为/dev/camera,如下
export LD_LIBRARY_PATH="$(pwd)"                                                 
./mjpg_streamer -o "output_http.so -w ./www" -i "input_s3c2410.so -d /dev/camera"
再次执行./start_s3c2410.sh
结果如下
MJPG Streamer Version.: 2.0
 DBG(input_s3c2410.c, input_init(), 95): argv[0]=S3C2410 embedded camera
 DBG(input_s3c2410.c, input_init(), 95): argv[1]=-d
 DBG(input_s3c2410.c, input_init(), 95): argv[2]=/dev/camera
 DBG(input_s3c2410.c, input_init(), 124): case d
 DBG(input_s3c2410.c, input_init(), 169): initializing s3c2410 device
 i: Using V4L2 device.: /dev/camera
 i: Desired Resolution: 640 x 512
 i: Grayscale mode: off
 DBG(s3c2410.c, init_s3c2410(), 63): Opening device
Error opening device /dev/camera: unable to query device.
 i: init_s3c2410 failed
即初始化时出现问题,不能查询设备。
根据提示找到源码s3c2410.c line 63附近
  DBG("Opening device\n");//line 63
  if ((vd->fd = open( vd->videodevice, O_RDWR)) == -1)
    exit_fatal ("ERROR opening V4L interface");

	
  memset(&vd->cap, 0, sizeof(struct v4l2_capability));
  err = ioctl(vd->fd, VIDIOC_QUERYCAP, &vd->cap);
  if (err < 0) {
    fprintf(stderr, "Error opening device %s: unable to query device.\n", vd->videodevice);
    return err;
  }
可知unable to query device.是由于设备不支持ioctl方法而导致的。
很奇怪哦,怎么友善给的编译好的mjpg-streamer-mini2440-bin-r6.tar.gz放在miroc2440上就可以直接使用,而下载的源码再编译就不可以了呢。。。
发现友善的编译好的是r6版本的,而用svn checkout http://mjpg-streamer-mini2440.googlecode.com/svn/trunk/ mjpg-streamer-mini2440-read-only下载到的是最新版本,而在最新版本中加入了ioctl方法对摄像头操作。所以要下一个r6版的mjpg-streamer。不必全下,只把r6版的s3c2410.c下载下来替换掉最新版里的s3c2410.c即可。
http://code.google.com/p/mjpg-streamer-mini2440/source/browse/trunk/plugins/input_s3c2410/s3c2410.c?r=6

再次按照上面所讲编译后下到板子上,执行start_s3c2410.sh,success!如下
[root@FriendlyARM bin6]# ./start_s3c2410.sh 
MJPG Streamer Version.: 2.0
 DBG(input_s3c2410.c, input_init(), 95): argv[0]=S3C2410 embedded camera
 DBG(input_s3c2410.c, input_init(), 95): argv[1]=-d
 DBG(input_s3c2410.c, input_init(), 95): argv[2]=/dev/camera
 DBG(input_s3c2410.c, input_init(), 124): case d
 DBG(input_s3c2410.c, input_init(), 169): initializing s3c2410 device
 i: Using V4L2 device.: /dev/camera
 i: Desired Resolution: 640 x 512
 i: Grayscale mode: off
 DBG(s3c2410.c, init_s3c2410(), 45): Opening device
 DBG(s3c2410.c, init_s3c2410(), 50): Allocating input buffers
Allocated
 DBG(output_http.c, output_init(), 85): output #00
 DBG(output_http.c, output_init(), 118): argv[0]=HTTP output plugin
 DBG(output_http.c, output_init(), 118): argv[1]=-w
 DBG(output_http.c, output_init(), 118): argv[2]=./www
 DBG(output_http.c, output_init(), 176): case 6,7
 o: www-folder-path...: ./www/
 o: HTTP TCP port.....: 8080
 o: username:password.: disabled
 o: commands..........: enabled
 DBG(mjpg_streamer.c, main(), 374): starting input plugin
 DBG(mjpg_streamer.c, main(), 382): starting 1 output plugin(s)
 DBG(output_http.c, output_run(), 229): launching server thread #00
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 1 times 176.177002
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 2 times 178.848999
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 3 times 175.275024
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 4 times 175.626953
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 5 times 174.866089
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 6 times 175.260986
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 7 times 175.651978
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 8 times 177.951050
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 9 times 175.342041
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 10 times 175.468018
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 11 times 175.126953
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 12 times 175.375000
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 13 times 175.416992
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 14 times 175.549072
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 15 times 175.479004
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 16 times 175.432007
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 17 times 175.218994
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 18 times 175.763062
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 19 times 175.397095
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 20 times 175.398926
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 21 times 176.143921
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 22 times 175.142944
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 23 times 175.319092
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 24 times 175.833984
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 25 times 175.234985
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 26 times 174.861938
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 27 times 178.566040
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 28 times 175.076050
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 29 times 175.467041
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 30 times 174.818970
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 31 times 176.250977
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 32 times 175.798096
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 33 times 177.946045
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 34 times 175.034912
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 35 times 175.500977
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 36 times 175.244995
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 37 times 175.006104
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 38 times 175.577026
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 39 times 177.815063
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 40 times 175.934082
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 41 times 175.211914
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 42 times 175.023926
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 43 times 175.515015
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 44 times 175.171997
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 11): "static.html"
 DBG(httpd.c, send_file(), 499): trying to serve file "static.html", extension: ".html" mime: "text/html"
 DBG(httpd.c, send_file(), 511): opened file: ./www/static.html
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 45 times 185.374023
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 9): "style.css"
 DBG(httpd.c, send_file(), 499): trying to serve file "style.css", extension: ".css" mime: "text/css"
 DBG(httpd.c, send_file(), 511): opened file: ./www/style.css
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 773): Request for snapshot
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 13): "sidebarbg.gif"
 DBG(httpd.c, send_file(), 499): trying to serve file "sidebarbg.gif", extension: ".gif" mime: "image/gif"
 DBG(httpd.c, send_file(), 511): opened file: ./www/sidebarbg.gif
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 10): "bodybg.gif"
 DBG(httpd.c, send_file(), 499): trying to serve file "bodybg.gif", extension: ".gif" mime: "image/gif"
 DBG(httpd.c, send_file(), 511): opened file: ./www/bodybg.gif
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 46 times 189.610962
 DBG(httpd.c, send_snapshot(), 310): got frame (size: 11 kB)
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 11): "favicon.ico"
 DBG(httpd.c, send_file(), 499): trying to serve file "favicon.ico", extension: ".ico" mime: "image/x-icon"
 DBG(httpd.c, send_file(), 511): opened file: ./www/favicon.ico
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 47 times 182.471924
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 48 times 174.978027
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 11): "stream.html"
 DBG(httpd.c, send_file(), 499): trying to serve file "stream.html", extension: ".html" mime: "text/html"
 DBG(httpd.c, send_file(), 511): opened file: ./www/stream.html
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 9): "style.css"
 DBG(httpd.c, send_file(), 499): trying to serve file "style.css", extension: ".css" mime: "text/css"
 DBG(httpd.c, send_file(), 511): opened file: ./www/style.css
 DBG(httpd.c, client_thread(), 777): Request for stream
 DBG(httpd.c, send_stream(), 340): preparing header
 DBG(httpd.c, send_stream(), 353): Headers send, sending stream now
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 49 times 200.244995
 DBG(httpd.c, send_stream(), 365): increasing buffer size to 11797
 DBG(httpd.c, send_stream(), 379): got frame (size: 11 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, send_stream(), 394): sending frame
 DBG(httpd.c, send_stream(), 397): sending boundary
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 10): "bodybg.gif"
 DBG(httpd.c, send_file(), 499): trying to serve file "bodybg.gif", extension: ".gif" mime: "image/gif"
 DBG(httpd.c, send_file(), 511): opened file: ./www/bodybg.gif
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 13): "sidebarbg.gif"
 DBG(httpd.c, send_file(), 499): trying to serve file "sidebarbg.gif", extension: ".gif" mime: "image/gif"
 DBG(httpd.c, send_file(), 511): opened file: ./www/sidebarbg.gif
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 11): "favicon.ico"
 DBG(httpd.c, send_file(), 499): trying to serve file "favicon.ico", extension: ".ico" mime: "image/x-icon"
 DBG(httpd.c, send_file(), 511): opened file: ./www/favicon.ico
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919):  DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 9): "java.html"
 DBG(httpd.c, send_file(), 499): trying to serve file "java.html", extension: ".html" mime: "text/html"
 DBG(httpd.c, send_file(), 511): opened file: ./www/java.html
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
waiting for clients to connect
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 50 times 191.764893
 DBG(httpd.c, send_stream(), 379): got frame (size: 11 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, send_stream(), 394): sending frame
 DBG(httpd.c, send_stream(), 397): sending boundary
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 9): "style.css"
 DBG(httpd.c, send_file(), 499): trying to serve file "style.css", extension: ".css" mime: "text/css"
 DBG(httpd.c, send_file(), 511): opened file: ./www/style.css
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 33): "com.charliemouse.cambozola.Viewer"
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 11): "LICENSE.txt"
 DBG(httpd.c, send_file(), 499): trying to serve file "LICENSE.txt", extension: ".txt" mime: "text/plain"
 DBG(httpd.c, send_file(), 511): opened file: ./www/LICENSE.txt
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 10): "bodybg.gif"
 DBG(httpd.c, send_file(), 499): trying to serve file "bodybg.gif", extension: ".gif" mime: "image/gif"
 DBG(httpd.c, send_file(), 511): opened file: ./www/bodybg.gif
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 13): "sidebarbg.gif"
 DBG(httpd.c, send_file(), 499): trying to serve file "sidebarbg.gif", extension: ".gif" mime: "image/gif"
 DBG(httpd.c, send_file(), 511): opened file: ./www/sidebarbg.gif
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 11): "favicon.ico"
 DBG(httpd.c, send_file(), 499): trying to serve file "favicon.ico", extension: ".ico" mime: "image/x-icon"
 DBG(httpd.c, send_file(), 511): opened file: ./www/favicon.ico
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 51 times 183.553955
 DBG(httpd.c, send_stream(), 379): got frame (size: 10 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, send_stream(), 394): sending frame
 DBG(httpd.c, send_stream(), 397): sending boundary
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 52 times 175.157959
 DBG(httpd.c, send_stream(), 379): got frame (size: 10 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 53 times 175.160034
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 11): "stream.html"
 DBG(httpd.c, send_file(), 499): trying to serve file "stream.html", extension: ".html" mime: "text/html"
 DBG(httpd.c, send_file(), 511): opened file: ./www/stream.html
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 777): Request for stream
 DBG(httpd.c, send_stream(), 340): preparing header
 DBG(httpd.c, send_stream(), 353): Headers send, sending stream now
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 9): "style.css"
 DBG(httpd.c, send_file(), 499): trying to serve file "style.css", extension: ".css" mime: "text/css"
 DBG(httpd.c, send_file(), 511): opened file: ./www/style.css
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 13): "sidebarbg.gif"
 DBG(httpd.c, send_file(), 499): trying to serve file "sidebarbg.gif", extension: ".gif" mime: "image/gif"
 DBG(httpd.c, send_file(), 511): opened file: ./www/sidebarbg.gif
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 10): "bodybg.gif"
 DBG(httpd.c, send_file(), 499): trying to serve file "bodybg.gif", extension: ".gif" mime: "image/gif"
 DBG(httpd.c, send_file(), 511): opened file: ./www/bodybg.gif
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 54 times 199.722046
 DBG(httpd.c, send_stream(), 365): increasing buffer size to 11124
 DBG(httpd.c, send_stream(), 379): got frame (size: 10 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, send_stream(), 394): sending frame
 DBG(httpd.c, send_stream(), 397): sending boundary
 DBG(httpd.c, server_thread(), 947): create thread to handle client that just established a connection
 DBG(httpd.c, server_thread(), 919): waiting for clients to connect
 DBG(httpd.c, client_thread(), 710): try to serve a file
 DBG(httpd.c, client_thread(), 729): parameter (len: 11): "favicon.ico"
 DBG(httpd.c, send_file(), 499): trying to serve file "favicon.ico", extension: ".ico" mime: "image/x-icon"
 DBG(httpd.c, send_file(), 511): opened file: ./www/favicon.ico
 DBG(httpd.c, client_thread(), 800): leaving HTTP client thread
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 55 times 182.822021
 DBG(httpd.c, send_stream(), 379): got frame (size: 11 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, send_stream(), 394): sending frame
 DBG(httpd.c, send_stream(), 397): sending boundary
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 56 times 177.759033
 DBG(httpd.c, send_stream(), 379): got frame (size: 11 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, send_stream(), 394): sending frame
 DBG(httpd.c, send_stream(), 397): sending boundary
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 57 times 175.708008
 DBG(httpd.c, send_stream(), 379): got frame (size: 11 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, send_stream(), 394): sending frame
 DBG(httpd.c, send_stream(), 397): sending boundary
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 58 times 177.897949
 DBG(httpd.c, send_stream(), 379): got frame (size: 10 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, send_stream(), 394): sending frame
 DBG(httpd.c, send_stream(), 397): sending boundary
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 59 times 175.118042
 DBG(httpd.c, send_stream(), 379): got frame (size: 10 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, send_stream(), 394): sending frame
 DBG(httpd.c, send_stream(), 397): sending boundary
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 60 times 175.838989
 DBG(httpd.c, send_stream(), 379): got frame (size: 11 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, send_stream(), 394): sending frame
 DBG(httpd.c, send_stream(), 397): sending boundary
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 61 times 175.480957
 DBG(httpd.c, send_stream(), 379): got frame (size: 10 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, send_stream(), 394): sending frame
 DBG(httpd.c, send_stream(), 397): sending boundary
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 62 times 181.625000
 DBG(httpd.c, send_stream(), 379): got frame (size: 10 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, send_stream(), 394): sending frame
 DBG(httpd.c, send_stream(), 397): sending boundary
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 63 times 175.881958
 DBG(httpd.c, send_stream(), 379): got frame (size: 10 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, send_stream(), 394): sending frame
 DBG(httpd.c, send_stream(), 397): sending boundary
 DBG(s3c2410.c, s3c2410_Grab(), 172): compress frame 64 times 178.318970
 DBG(httpd.c, send_stream(), 379): got frame (size: 11 kB)
 DBG(httpd.c, send_stream(), 391): sending intemdiate header
 DBG(httpd.c, send_stream(), 394): sending frame
 DBG(httpd.c, send_stream(), 397): sending boundary

我稍微修改过的mjpg-streamer源码
http://download.csdn.net/detail/songqqnew/3841684
**************************************************************************************************************************************************************
先看几个结构体
/******************************************************************mjpg-streamer.h***************************/
typedef struct _globals globals;
struct _globals {
  int stop;			//控制读写线程的读写动作进行与否

  /* signal fresh frames */
  pthread_mutex_t db;		//互斥量,用于读和写线程的同步
  pthread_cond_t  db_update;	

  /* global JPG frame, this is more or less the "database" */
  unsigned char *buf;		//全局数据区域,图像数据
  int size;			//图像数据大小

  /* input plugin */
  input in;			//输入模块

  /* output plugin */
  output out[MAX_OUTPUT_PLUGINS];//输出模块   #define MAX_OUTPUT_PLUGINS 10,可知最多能同时将图像数据输出到10个地方,比如到file,到http
  int outcnt;			//输出数目,即记录命令参数中有几个 -o

};


/******************************************************************plugins/input.h***************************/
/* structure to store variables/functions for input plugin */
typedef struct _input input;
struct _input {
  char *plugin;			//so文件名,比如-i "input_s3c2410.so -d  /dev/camera -r 320x240",则plugin="input_s3c2410.so"
  void *handle;			//so句柄
  input_parameter param;	//参数

  int (*init)(input_parameter *);//初始化函数指针
  int (*stop)(void);		 //打开函数指针
  int (*run)(void);		 //执行函数指针
  int (*cmd)(in_cmd_type, int);  //命令函数指针
};



/* parameters for input plugin */
typedef struct _input_parameter input_parameter;
struct _input_parameter {
  char *parameter_string;	//比如-i "input_s3c2410.so -d  /dev/camera -r 320x240",则parameter_string="-d  /dev/camera -r 320x240"
  struct _globals *global;	//回指全局结构体
};

/******************************************************************plugins/output.h***************************/
/* structure to store variables/functions for output plugin */
typedef struct _output output;
struct _output {
  char *plugin;				//比如 -o "output_http.so -w ./www",则plugin="output_http.so"
  void *handle;				//so句柄	
  output_parameter param;	       //参数

  int (*init)(output_parameter *);
  int (*stop)(int);
  int (*run)(int);
  int (*cmd)(int, out_cmd_type, int);
};

/* parameters for output plugin */
typedef struct _output_parameter output_parameter;
struct _output_parameter {
  int id;				//记录这是第几个输出(-o)
  char *parameter_string;               //比如 -o "output_http.so -w ./www",则parameter_string="-w ./www"
  struct _globals *global;              //回指全局结构体
};


//mjpg-streamer.c
/*******************************************************************************
#                                                                              #
#      MJPG-streamer allows to stream JPG frames from an input-plugin          #
#      to several output plugins                                               #
#                                                                              #
#      Copyright (C) 2007 Tom St枚veken                                         #
#                                                                              #
# This program is free software; you can redistribute it and/or modify         #
# it under the terms of the GNU General Public License as published by         #
# the Free Software Foundation; version 2 of the License.                      #
#                                                                              #
# This program is distributed in the hope that it will be useful,              #
# but WITHOUT ANY WARRANTY; without even the implied warranty of               #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                #
# GNU General Public License for more details.                                 #
#                                                                              #
# You should have received a copy of the GNU General Public License            #
# along with this program; if not, write to the Free Software                  #
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    #
#                                                                              #
*******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <linux/videodev.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <getopt.h>
#include <pthread.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <syslog.h>

#include "utils.h"
#include "mjpg_streamer.h"

/* globals */
static globals global;

/******************************************************************************
Description.: Display a help message
Input Value.: argv[0] is the program name and the parameter progname
Return Value: -
******************************************************************************/
void help(char *progname)
{
  fprintf(stderr, "-----------------------------------------------------------------------\n");
  fprintf(stderr, "Usage: %s\n" \
                  "  -i | --input \"<input-plugin.so> [parameters]\"\n" \
                  "  -o | --output \"<output-plugin.so> [parameters]\"\n" \
                  " [-h | --help ]........: display this help\n" \
                  " [-v | --version ].....: display version information\n" \
                  " [-b | --background]...: fork to the background, daemon mode\n", progname);
  fprintf(stderr, "-----------------------------------------------------------------------\n");
  fprintf(stderr, "Example #1:\n" \
                  " To open an UVC webcam \"/dev/video1\" and stream it via HTTP:\n" \
                  "  %s -i \"input_uvc.so -d /dev/video1\" -o \"output_http.so\"\n", progname);
  fprintf(stderr, "-----------------------------------------------------------------------\n");
  fprintf(stderr, "Example #2:\n" \
                  " To open an UVC webcam and stream via HTTP port 8090:\n" \
                  "  %s -i \"input_uvc.so\" -o \"output_http.so -p 8090\"\n", progname);
  fprintf(stderr, "-----------------------------------------------------------------------\n");
  fprintf(stderr, "Example #3:\n" \
                  " To get help for a certain input plugin:\n" \
                  "  %s -i \"input_uvc.so --help\"\n", progname);
  fprintf(stderr, "-----------------------------------------------------------------------\n");
  fprintf(stderr, "In case the modules (=plugins) can not be found:\n" \
                  " * Set the default search path for the modules with:\n" \
                  "   export LD_LIBRARY_PATH=/path/to/plugins,\n" \
                  " * or put the plugins into the \"/lib/\" or \"/usr/lib\" folder,\n" \
                  " * or instead of just providing the plugin file name, use a complete\n" \
                  "   path and filename:\n" \
                  "   %s -i \"/path/to/modules/input_uvc.so\"\n", progname);
  fprintf(stderr, "-----------------------------------------------------------------------\n");
}

/******************************************************************************
Description.: pressing CTRL+C sends signals to this process instead of just
              killing it plugins can tidily shutdown and free allocated
              ressources. The function prototype is defined by the system,
              because it is a callback function.
Input Value.: sig tells us which signal was received
Return Value: -
******************************************************************************/
void signal_handler(int sig)
{
  int i;

  /* signal "stop" to threads */
  LOG("setting signal to stop\n");
  global.stop = 1;
  usleep(1000*1000);

  /* clean up threads */
  LOG("force cancelation of threads and cleanup ressources\n");
  global.in.stop();
  for(i=0; i<global.outcnt; i++) {
    global.out[i].stop(global.out[i].param.id);
  }
  usleep(1000*1000);

  /* close handles of input plugins */
  dlclose(&global.in.handle);
  for(i=0; i<global.outcnt; i++) {
    /* skip = 0;
    DBG("about to decrement usage counter for handle of %s, id #%02d, handle: %p\n", \
        global.out[i].plugin, global.out[i].param.id, global.out[i].handle);
    for(j=i+1; j<global.outcnt; j++) {
      if ( global.out[i].handle == global.out[j].handle ) {
        DBG("handles are pointing to the same destination (%p == %p)\n", global.out[i].handle, global.out[j].handle);
        skip = 1;
      }
    }
    if ( skip ) {
      continue;
    }

    DBG("closing handle %p\n", global.out[i].handle);
    */
    dlclose(global.out[i].handle);
  }
  DBG("all plugin handles closed\n");

  pthread_cond_destroy(&global.db_update);
  pthread_mutex_destroy(&global.db);

  LOG("done\n");

  closelog();
  exit(0);
  return;
}

/******************************************************************************
Description.: 
Input Value.: 
Return Value: 
******************************************************************************/
int control(int command, char *details) {

  switch(command) {
    case CONTROL_CMD_RECONFIGURE_INPUT:
      printf("will reload input plugin: %s\n", details);
      break;
    default:
      LOG("unknown control command received\n");
  }
  return 0;
}


/******************************************************************************
Description.: 
Input Value.: 
Return Value: 
******************************************************************************/
int main(int argc, char *argv[])
{
  char *input  = "input_uvc.so --resolution 640x480 --fps 5 --device /dev/video0";
  char *output[MAX_OUTPUT_PLUGINS];
  int daemon=0, i;
  size_t tmp=0;

  output[0] = "output_http.so --port 8080";
  global.outcnt = 0;

  global.control = control;

  /* parameter parsing */
  while(1) {
    int option_index = 0, c=0;
    static struct option long_options[] = \
    {
      {"h", no_argument, 0, 0},
      {"help", no_argument, 0, 0},
      {"i", required_argument, 0, 0},
      {"input", required_argument, 0, 0},
      {"o", required_argument, 0, 0},
      {"output", required_argument, 0, 0},
      {"v", no_argument, 0, 0},
      {"version", no_argument, 0, 0},
      {"b", no_argument, 0, 0},
      {"background", no_argument, 0, 0},
      {0, 0, 0, 0}
    };

    c = getopt_long_only(argc, argv, "", long_options, &option_index);

    /* no more options to parse */
    if (c == -1) break;

    /* unrecognized option */
    if(c=='?'){ help(argv[0]); return 0; }

    switch (option_index) {
      /* h, help */
      case 0:
      case 1:
        help(argv[0]);
        return 0;
        break;

      /* i, input */
      case 2:
      case 3:
        input = strdup(optarg);
        break;

      /* o, output */
      case 4:
      case 5:
        output[global.outcnt++] = strdup(optarg);//每遇到一个-o选项outcnt就+1,,所以outcnt代表输出的个数
        break;

      /* v, version */
      case 6:
      case 7:
        printf("MJPG Streamer Version: %s\n" \
               "Compilation Date.....: %s\n" \
               "Compilation Time.....: %s\n", SOURCE_VERSION, __DATE__, __TIME__);
        return 0;
        break;

      /* b, background */
      case 8:
      case 9:
        daemon=1;
        break;

      default:
        help(argv[0]);
        return 0;
    }
  }
  
  openlog("MJPG-streamer ", LOG_PID|LOG_CONS, LOG_USER);
  //openlog("MJPG-streamer ", LOG_PID|LOG_CONS|LOG_PERROR, LOG_USER);
  syslog(LOG_INFO, "starting application");

  /* fork to the background */
  if ( daemon ) {
    LOG("enabling daemon mode");
    daemon_mode();
  }
/*************************************************************************************初始化***************************/
  /* initialise the global variables 初始化全局变量*/
  global.stop      = 0;
  global.buf       = NULL;
  global.size      = 0;
  global.in.plugin = NULL;

  /* this mutex and the conditional variable are used to synchronize access to the global picture buffer 
互斥量和条件变量
*/
  if( pthread_mutex_init(&global.db, NULL) != 0 ) {
    LOG("could not initialize mutex variable\n");
    closelog();
    exit(EXIT_FAILURE);
  }
  if( pthread_cond_init(&global.db_update, NULL) != 0 ) {
    LOG("could not initialize condition variable\n");
    closelog();
    exit(EXIT_FAILURE);
  }

  /* ignore SIGPIPE (send by OS if transmitting to closed TCP sockets) */
  signal(SIGPIPE, SIG_IGN);

  /* register signal handler for <CTRL>+C in order to clean up */
  if (signal(SIGINT, signal_handler) == SIG_ERR) {
    LOG("could not register signal handler\n");
    closelog();
    exit(EXIT_FAILURE);
  }

  /*
   * messages like the following will only be visible on your terminal
   * if not running in daemon mode
   */
  LOG("MJPG Streamer Version.: %s\n", SOURCE_VERSION);

  /* check if at least one output plugin was selected */
  if ( global.outcnt == 0 ) {
    /* no? Then use the default plugin instead */
    global.outcnt = 1;
  }
/*************************************************************************************global.in.init(&global.in.param)**********************/
  /* open input plugin */
  tmp = (size_t)(strchr(input, ' ')-input);
  global.in.plugin = (tmp > 0)?strndup(input, tmp):strdup(input);
  //比如./mjpg_streamer -o "output_http.so -w ./www" -i "input_s3c2410.so -d  /dev/camera -r 320x240"
  //则char*  input="input_s3c2410.so -d  /dev/camera -r 320x240"
  //则char*  global.in.plugin ="input_s3c2410.so"

  global.in.handle = dlopen(global.in.plugin, RTLD_LAZY);
  //以RTLD_LAZY方式打开input_s3c2410.so,装载进内存
  //RTLD_LAZY延迟绑定
  //可见各个so都是以插件形式装载进内存
  //一般需要动态链接器去装载
  if ( !global.in.handle ) {
    LOG("ERROR: could not find input plugin\n");
    LOG("       Perhaps you want to adjust the search path with:\n");
    LOG("       # export LD_LIBRARY_PATH=/path/to/plugin/folder\n");
    LOG("       dlopen: %s\n", dlerror() );
    closelog();
    exit(EXIT_FAILURE);
  }

  global.in.init = dlsym(global.in.handle, "input_init");
//查找符号,在刚装载的模块比如input_s3c2410.so内存单元范围内中查找符号input_init,其虚拟地址已经确定
//找到,返回地址,赋给结构体global的成员结构体in的成员init函数指针
//即用input_init去填充in结构体的函数指针init
  if ( global.in.init == NULL ) {
    LOG("%s\n", dlerror());
    exit(EXIT_FAILURE);
  }

  global.in.stop = dlsym(global.in.handle, "input_stop");
//查找符号,在刚装载的模块比如input_s3c2410.so内存单元范围内中查找符号input_stop,
  if ( global.in.stop == NULL ) {
    LOG("%s\n", dlerror());
    exit(EXIT_FAILURE);
  }

  global.in.run = dlsym(global.in.handle, "input_run");
//查找符号,在刚装载的模块比如input_s3c2410.so内存单元范围内中查找符号input_run,
  if ( global.in.run == NULL ) {
    LOG("%s\n", dlerror());
    exit(EXIT_FAILURE);
  }

  /* try to find optional command */
  global.in.cmd = dlsym(global.in.handle, "input_cmd");
//查找符号,在刚装载的模块比如input_s3c2410.so内存单元范围内中查找符号input_cmd,

  global.in.param.parameter_string = strchr(input, ' ');
  //比如./mjpg_streamer -o "output_http.so -w ./www" -i "input_s3c2410.so -d /dev/camera -r 320x240"
  //则char*  input="input_s3c2410.so -d  /dev/camera -r 320x240"
  //则char*  global.in.plugin ="input_s3c2410.so"
  //则char*  global.in.param.parameter_string ="-d /dev/camera -r 320x240"

  global.in.param.global = &global;

  if ( global.in.init(&global.in.param) ) {
    LOG("input_init() return value signals to exit");
    closelog();
    exit(0);
  }

/*************************************************************************************global.out[i].init(&global.out[i].param)*******************/

  /* open output plugin */
  for (i=0; i<global.outcnt; i++) {
    tmp = (size_t)(strchr(output[i], ' ')-output[i]);
    global.out[i].plugin = (tmp > 0)?strndup(output[i], tmp):strdup(output[i]);
    global.out[i].handle = dlopen(global.out[i].plugin, RTLD_LAZY);
  //比如./mjpg_streamer -o "output_http.so -w ./www" -i "input_s3c2410.so -d  /dev/camera -r 320x240"
  //则char*  output[0]="output_http.so -w ./www"
  //则char*  global.out[0].plugin ="output_http.so"

    if ( !global.out[i].handle ) {
      LOG("ERROR: could not find output plugin %s\n", global.out[i].plugin);
      LOG("       Perhaps you want to adjust the search path with:\n");
      LOG("       # export LD_LIBRARY_PATH=/path/to/plugin/folder\n");
      LOG("       dlopen: %s\n", dlerror() );
      closelog();
      exit(EXIT_FAILURE);
    }
    global.out[i].init = dlsym(global.out[i].handle, "output_init");
    if ( global.out[i].init == NULL ) {
      LOG("%s\n", dlerror());
      exit(EXIT_FAILURE);
    }
    global.out[i].stop = dlsym(global.out[i].handle, "output_stop");
    if ( global.out[i].stop == NULL ) {
      LOG("%s\n", dlerror());
      exit(EXIT_FAILURE);
    }
    global.out[i].run = dlsym(global.out[i].handle, "output_run");
    if ( global.out[i].run == NULL ) {
      LOG("%s\n", dlerror());
      exit(EXIT_FAILURE);
    }
    /* try to find optional command */
    global.out[i].cmd = dlsym(global.out[i].handle, "output_cmd");

    global.out[i].param.parameter_string = strchr(output[i], ' ');
  //比如./mjpg_streamer -o "output_http.so -w ./www" -i "input_s3c2410.so -d  /dev/camera -r 320x240"
  //则char*  output[0]="output_http.so -w ./www"
  //则char*  global.out[0].plugin ="output_http.so"
  //则char*  global.out[0].param.parameter_string ="-w ./www"

    global.out[i].param.global = &global;
    global.out[i].param.id = i;
//i用于记录-o的索引,表示第几个输出(-o)

    if ( global.out[i].init(&global.out[i].param) ) {
      LOG("output_init() return value signals to exit");
      closelog();
      exit(0);
    }
  }
/*************************************************************************************global.in.run()***************************/
  /* start to read the input, push pictures into global buffer */
  DBG("starting input plugin\n");
  syslog(LOG_INFO, "starting input plugin");
  if ( global.in.run() ) {
    LOG("can not run input plugin\n");
    closelog();
    return 1;
  }
/*************************************************************************************global.out[i].run(global.out[i].param.id)************/
  DBG("starting %d output plugin(s)\n", global.outcnt);
  for(i=0; i<global.outcnt; i++) {
    syslog(LOG_INFO, "starting output plugin: %s (ID: %02d)", global.out[i].plugin, global.out[i].param.id);
    global.out[i].run(global.out[i].param.id);
////传递的是id(表示第几个-o)
  }

  /* wait for signals */
  pause();

  return 0;
}

可知mjpg-streamer.c的作用主要是接受并分析启动参数,然后去加载起读写作用的部分--插件即那几个so.并
从输入插件中寻找以下符号
input_init()
input_stop()
input_run()
input_cmd()
从输出插件中寻找以下符号
output_init()
output_stop()
output_run()
output_cmd()
分别赋给globals的对应函数指针
然后执行
input_init(),output_init(),input_run(),output_run(),跳到对应代码里面。见下文。
posted on 2011-11-23 21:29  _song  阅读(653)  评论(0编辑  收藏  举报