⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ffserver.c

📁 杜比AC-3编码解码器(参考程序)
💻 C
📖 第 1 页 / 共 4 页
字号:
                audio_enc.bit_rate = atoi(arg) * 1000;
            }
        } else if (!strcasecmp(cmd, "AudioChannels")) {
            get_arg(arg, sizeof(arg), &p);
            if (stream) {
                audio_enc.channels = atoi(arg);
            }
        } else if (!strcasecmp(cmd, "AudioSampleRate")) {
            get_arg(arg, sizeof(arg), &p);
            if (stream) {
                audio_enc.rate = atoi(arg);
            }
        } else if (!strcasecmp(cmd, "VideoBitRate")) {
            get_arg(arg, sizeof(arg), &p);
            if (stream) {
                video_enc.bit_rate = atoi(arg) * 1000;
            }
        } else if (!strcasecmp(cmd, "VideoFrameRate")) {
            get_arg(arg, sizeof(arg), &p);
            if (stream) {
                video_enc.rate = atoi(arg);
            }
        } else if (!strcasecmp(cmd, "VideoGopSize")) {
            get_arg(arg, sizeof(arg), &p);
            if (stream) {
                video_enc.gop_size = atoi(arg);
            }
        } else if (!strcasecmp(cmd, "VideoIntraOnly")) {
            if (stream) {
                video_enc.gop_size = 1;
            }
        } else if (!strcasecmp(cmd, "</Stream>")) {
            if (!stream) {
                fprintf(stderr, "%s:%d: No corresponding <Stream> for </Stream>\n",
                        filename, line_num);
                errors++;
            }
            if (stream->fmt) {
                if (stream->fmt->audio_codec != CODEC_ID_NONE) {
                    stream->audio_enc = add_codec(stream->fmt->audio_codec,
                                                  &audio_enc);
                }
                
                if (stream->fmt->video_codec != CODEC_ID_NONE)
                    stream->video_enc = add_codec(stream->fmt->video_codec,
                                                  &video_enc);
            }
            stream = NULL;
        } else {
            fprintf(stderr, "%s:%d: Incorrect keyword: '%s'\n", 
                    filename, line_num, cmd);
            errors++;
        }
    }

    fclose(f);
    if (errors)
        return -1;
    else
        return 0;
}


void *http_server_thread(void *arg)
{
    http_server(my_addr);
    return NULL;
}

static void write_packet(FFCodec *ffenc,
                         UINT8 *buf, int size)
{
    PacketHeader hdr;
    AVEncodeContext *enc = &ffenc->enc;
    UINT8 *wptr;
    mk_header(&hdr, enc, size);
    wptr = http_fifo.wptr;
    fifo_write(&http_fifo, (UINT8 *)&hdr, sizeof(hdr), &wptr);
    fifo_write(&http_fifo, buf, size, &wptr);
    /* atomic modification of wptr */
    http_fifo.wptr = wptr;
    ffenc->data_count += size;
    ffenc->avg_frame_size = ffenc->avg_frame_size * AVG_COEF + size * (1.0 - AVG_COEF);
}

#define AUDIO_FIFO_SIZE 8192

int av_grab(void)
{
    UINT8 audio_buf[AUDIO_FIFO_SIZE/2];
    UINT8 audio_buf1[AUDIO_FIFO_SIZE/2];
    UINT8 audio_out[AUDIO_FIFO_SIZE/2];
    UINT8 video_buffer[128*1024];
    char buf[256];
    short *samples;
    int ret;
    int audio_fd;
    FFCodec *ffenc;
    AVEncodeContext *enc;
    int frame_size, frame_bytes;
    int use_audio, use_video;
    int frame_rate, sample_rate, channels;
    int width, height, frame_number;
    UINT8 *picture[3];

    use_audio = 0;
    use_video = 0;
    frame_rate = 0;
    sample_rate = 0;
    frame_size = 0;
    channels = 1;
    width = 0;
    height = 0;
    frame_number = 0;
    ffenc = first_codec;
    while (ffenc != NULL) {
        enc = &ffenc->enc;
        avencoder_string(buf, sizeof(buf), enc);
        fprintf(stderr, "  %s\n", buf);
        if (avencoder_open(enc, enc->codec) < 0) {
            fprintf(stderr, "Incorrect encode parameters\n");
            return -1;
        }
        switch(enc->codec->type) {
        case CODEC_TYPE_AUDIO:
            use_audio = 1;
            if (enc->rate > sample_rate)
                sample_rate = enc->rate;
            if (enc->frame_size > frame_size)
                frame_size = enc->frame_size;
            if (enc->channels > channels)
                channels = enc->channels;
            fifo_init(&ffenc->fifo, AUDIO_FIFO_SIZE);
            break;
        case CODEC_TYPE_VIDEO:
            use_video = 1;
            if (enc->rate > frame_rate)
                frame_rate = enc->rate;
            if (enc->width > width)
                width = enc->width;
            if (enc->height > height)
                height = enc->height;
            break;
        }
        ffenc = ffenc->next;
    }

    /* audio */
    samples = NULL;
    audio_fd = -1;
    if (use_audio) {
        printf("Audio sampling: %d Hz, %s\n", 
               sample_rate, channels == 2 ? "stereo" : "mono");
        audio_fd = audio_open(sample_rate, channels);
        if (audio_fd < 0) {
            fprintf(stderr, "Could not open audio device\n");
            exit(1);
        }
    }
    
    ffenc = first_codec;
    while (ffenc != NULL) {
        enc = &ffenc->enc;
        if (enc->codec->type == CODEC_TYPE_AUDIO &&
            (enc->channels != channels ||
             enc->rate != sample_rate)) {
            audio_resample_init(&ffenc->resample, enc->channels, channels,
                                enc->rate, sample_rate);
        }
        ffenc = ffenc->next;
    }

    /* video */
    if (use_video) {
        printf("Video sampling: %dx%d, %d fps\n", 
               width, height, frame_rate);
        ret = v4l_init(frame_rate, width, height);
        if (ret < 0) {
            fprintf(stderr,"Could not init video 4 linux capture\n");
            exit(1);
        }
    }

    for(;;) {
        /* read & compress audio frames */
        if (use_audio) {
            int ret, nb_samples, nb_samples_out;
            UINT8 *buftmp;

            for(;;) {
                ret = read(audio_fd, audio_buf, AUDIO_FIFO_SIZE/2);
                if (ret <= 0)
                    break;
                /* fill each codec fifo by doing the right sample
                   rate conversion. This is not optimal because we
                   do too much work, but it is easy to do */
                nb_samples = ret / (channels * 2);
                ffenc = first_codec;
                while (ffenc != NULL) {
                    enc = &ffenc->enc;
                    if (enc->codec->type == CODEC_TYPE_AUDIO) {
                        /* rate & stereo convertion */
                        if (enc->channels == channels &&
                            enc->rate == sample_rate) {
                            buftmp = audio_buf;
                            nb_samples_out = nb_samples;
                        } else {
                            buftmp = audio_buf1;
                            nb_samples_out = audio_resample(&ffenc->resample, 
                                                            (short *)buftmp, (short *)audio_buf,
                                                            nb_samples);
                            
                        }
                        fifo_write(&ffenc->fifo, buftmp, nb_samples_out * enc->channels * 2, 
                                   &ffenc->fifo.wptr);
                    }
                    ffenc = ffenc->next;
                }
                
                /* compress as many frame as possible with each audio codec */
                ffenc = first_codec;
                while (ffenc != NULL) {
                    enc = &ffenc->enc;
                    if (enc->codec->type == CODEC_TYPE_AUDIO) {
                        frame_bytes = enc->frame_size * 2 * enc->channels;
                        
                        while (fifo_read(&ffenc->fifo, audio_buf, frame_bytes, &ffenc->fifo.rptr) == 0) {
                            ret = avencoder_encode(enc,
                                                   audio_out, sizeof(audio_out), audio_buf);
                            write_packet(ffenc, audio_out, ret);
                        }
                    }
                    ffenc = ffenc->next;
                }
            }
        }

        if (use_video) {
            ret = v4l_read_picture (picture, width, height, 
                                    frame_number);
            if (ret < 0)
                break;
            ffenc = first_codec;
            while (ffenc != NULL) {
                enc = &ffenc->enc;
                if (enc->codec->type == CODEC_TYPE_VIDEO) {
                    int n1, n2;
                    /* feed each codec with its requested frame rate */
                    n1 = (frame_number * enc->rate) / frame_rate;
                    n2 = ((frame_number + 1) * enc->rate) / frame_rate;
                    if (n2 > n1) {
                        ret = avencoder_encode(enc, video_buffer, sizeof(video_buffer), picture);
                        write_packet(ffenc, video_buffer, ret);
                    }
                }
                ffenc = ffenc->next;
            }
            frame_number++;
        }
    }
    
    ffenc = first_codec;
    while (ffenc != NULL) {
        enc = &ffenc->enc;
        avencoder_close(enc);
        ffenc = ffenc->next;
    }
    close(audio_fd);
    return 0;
}


void help(void)
{
    printf("ffserver version " FFMPEG_VERSION ", Copyright (c) 2000,2001 Gerard Lantau\n"
           "usage: ffserver [-L] [-h] [-f configfile]\n"
           "Hyper fast multi format Audio/Video streaming server\n"
           "\n"
           "-L            : print the LICENCE\n"
           "-h            : this help\n"
           "-f configfile : use configfile instead of /etc/ffserver.conf\n"
           );
}

void licence(void)
{
    printf(
    "ffserver version " FFMPEG_VERSION "\n"
    "Copyright (c) 2000,2001 Gerard Lantau\n"
    "This program is free software; you can redistribute it and/or modify\n"
    "it under the terms of the GNU General Public License as published by\n"
    "the Free Software Foundation; either version 2 of the License, or\n"
    "(at your option) any later version.\n"
    "\n"
    "This program is distributed in the hope that it will be useful,\n"
    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
    "GNU General Public License for more details.\n"
    "\n"
    "You should have received a copy of the GNU General Public License\n"
    "along with this program; if not, write to the Free Software\n"
    "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
    );
}

int main(int argc, char **argv)
{
    pthread_t http_server_tid;
    const char *config_filename;
    int c;

    /* codecs */
    register_avencoder(&ac3_encoder);
    register_avencoder(&mp2_encoder);
    register_avencoder(&mpeg1video_encoder);
    register_avencoder(&h263_encoder);
    register_avencoder(&rv10_encoder);
    register_avencoder(&mjpeg_encoder);
    register_avencoder(&divx_encoder);

    /* audio video formats */
    register_avformat(&mp2_format);
    register_avformat(&ac3_format);
    register_avformat(&mpeg_mux_format);
    register_avformat(&mpeg1video_format);
    register_avformat(&h263_format);
    register_avformat(&rm_format);
    register_avformat(&ra_format);
    register_avformat(&asf_format);
    register_avformat(&avi_format);
    register_avformat(&mpjpeg_format);
    register_avformat(&jpeg_format);
    register_avformat(&swf_format);

    config_filename = "/etc/ffserver.conf";

    for(;;) {
        c = getopt_long_only(argc, argv, "Lh?f:", NULL, NULL);
        if (c == -1)
            break;
        switch(c) {
        case 'L':
            licence();
            exit(1);
        case '?':
        case 'h':
            help();
            exit(1);
        case 'f':
            config_filename = optarg;
            break;
        default:
            exit(2);
        }
    }

    /* address on which the server will handle connections */
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons (8080);
    my_addr.sin_addr.s_addr = htonl (INADDR_ANY);
    nb_max_connections = 5;
    first_stream = NULL;
    logfilename[0] = '\0';

    if (parse_ffconfig(config_filename) < 0) {
        fprintf(stderr, "Incorrect config file - exiting.\n");
        exit(1);
    }

    /* signal init */
    signal(SIGPIPE, SIG_IGN);

    /* open log file if needed */
    if (logfilename[0] != '\0') {
        if (!strcmp(logfilename, "-"))
            logfile = stdout;
        else
            logfile = fopen(logfilename, "w");
    }

    /* init fifo */
    http_fifo_write_count = 0;
    if (fifo_init(&http_fifo, FIFO_MAX_SIZE) < 0) {
        fprintf(stderr, "Could not allow receive fifo\n");
        exit(1);
    }

    if (master_url[0] == '\0') {
        /* no master server: we grab ourself */

        /* launch server thread */
        if (pthread_create(&http_server_tid, NULL, 
                           http_server_thread, NULL) != 0) {
            fprintf(stderr, "Could not create http server thread\n");
            exit(1);
        }

        /* launch the audio / video grab */
        if (av_grab() < 0) {
            fprintf(stderr, "Could not start audio/video grab\n");
            exit(1);
        }
    } else {
        /* master server : no thread are needed */
        if (http_server(my_addr) < 0) {
            fprintf(stderr, "Could start http server\n");
            exit(1);
        }
    }

    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -