Mercurial > mplayer.hg
view TOOLS/netstream.c @ 23978:ef6e50c3c172
Revert setting audio output channel count for FFmpeg
The FFmpeg API needs to be fixed before this can be done sanely.
ffdca wants the desired output channel count to be set in
avctx->channels. Unfortunately it also completely fails if the requested
number of channels is not available rather than returning a different
amount (if 6 channels are requested we'd probably rather use stereo than
fail completely).
ffvorbis ignores caller-set values in avctx->channels. It writes the
channel count there once during init. This means the caller can only
set the count before init because later there would be no indication
whether the channel count in avctx reflects real output.
ffwma requires the caller to supply the encoded channel count
in avctx->channels during init or it fails. So it is not possible to
set a different number of desired output channels there before init
either.
author | uau |
---|---|
date | Thu, 02 Aug 2007 21:54:14 +0000 |
parents | d258dd05e0ab |
children | fe3fd951b8cc |
line wrap: on
line source
/* * netstream.c * * Copyright (C) Alban Bedel - 04/2003 * * This file is part of MPlayer, a free movie player. * * MPlayer 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; either version 2, or (at your option) * any later version. * * MPlayer 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 MPlayer; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <inttypes.h> #include <errno.h> #include <signal.h> #include <sys/types.h> #include "config.h" #ifndef HAVE_WINSOCK2 #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #else #include <winsock2.h> #include <ws2tcpip.h> #endif #include "stream/stream.h" #include "libmpdemux/demuxer.h" #include "mp_msg.h" #include "libavutil/common.h" #include "mpbswap.h" /// Netstream packets def and some helpers #include "stream/netstream.h" //Set some standard variables char* dvdsub_lang=NULL; char* audio_lang=NULL; int sub_justify=0; int identify=0; int dvdsub_id=0; int audio_id=0; int video_id=0; void af_fmt2str() {}; #ifdef __MINGW32__ #define usleep sleep void strsep() {}; #endif static unsigned short int port = 10000; typedef struct client_st client_t; struct client_st { int fd; stream_t* stream; client_t* next; client_t* prev; }; static int write_error(int fd,char* msg) { int len = strlen(msg) + 1; return write_packet(fd,NET_STREAM_ERROR,msg,len); } static int net_stream_open(client_t* cl,char* url) { int file_format=DEMUXER_TYPE_UNKNOWN; mp_net_stream_opened_t ret; if(cl->stream) { if(!write_error(cl->fd,"A stream is currently opened\n")) return 0; return 1; } mp_msg(MSGT_NETST,MSGL_V,"Open stream %s\n",url); cl->stream = open_stream(url,NULL,&file_format); if(!cl->stream) { if(!write_error(cl->fd,"Open failed\n")) return 0; return 1; } stream_reset(cl->stream); stream_seek(cl->stream,cl->stream->start_pos); ret.file_format = file_format; ret.flags = cl->stream->flags; ret.sector_size = cl->stream->sector_size; ret.start_pos = cl->stream->start_pos; ret.end_pos = cl->stream->end_pos; net_stream_opened_2_me(&ret); if(!write_packet(cl->fd,NET_STREAM_OK,(char*)&ret,sizeof(mp_net_stream_opened_t))) return 0; return 1; } static int net_stream_fill_buffer(client_t* cl,uint16_t max_len) { int r; mp_net_stream_packet_t *pack; if(!cl->stream) { if(!write_error(cl->fd,"No stream is currently opened\n")) return 0; return 1; } if(max_len == 0) { if(!write_error(cl->fd,"Fill buffer called with 0 lenght\n")) return 0; return 1; } pack = malloc(max_len + sizeof(mp_net_stream_packet_t)); pack->cmd = NET_STREAM_OK; r = stream_read(cl->stream,pack->data,max_len); pack->len = le2me_16(r + sizeof(mp_net_stream_packet_t)); if(!net_write(cl->fd,(char*)pack,le2me_16(pack->len))) { free(pack); return 0; } free(pack); return 1; } static int net_stream_seek(client_t* cl, uint64_t pos) { if(!cl->stream) { if(!write_error(cl->fd,"No stream is currently opened\n")) return 0; return 1; } if(!stream_seek(cl->stream,(off_t)pos)) { if(!write_error(cl->fd,"Seek failed\n")) return 0; return 1; } if(!write_packet(cl->fd,NET_STREAM_OK,NULL,0)) return 0; return 1; } static int net_stream_reset(client_t* cl) { if(!cl->stream) { if(!write_error(cl->fd,"No stream is currently opened\n")) return 0; return 1; } stream_reset(cl->stream); if(!write_packet(cl->fd,NET_STREAM_OK,NULL,0)) return 0; return 1; } static int net_stream_close(client_t* cl) { if(!cl->stream) { if(!write_error(cl->fd,"No stream is currently opened\n")) return 0; return 1; } free_stream(cl->stream); cl->stream = NULL; if(!write_packet(cl->fd,NET_STREAM_OK,NULL,0)) return 0; return 1; } int handle_client(client_t* cl,mp_net_stream_packet_t* pack) { if(!pack) return 0; switch(pack->cmd) { case NET_STREAM_OPEN: if(((char*)pack)[pack->len-1] != '\0') { mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid open packet\n"); return 0; } return net_stream_open(cl,pack->data); case NET_STREAM_FILL_BUFFER: if(pack->len != sizeof(mp_net_stream_packet_t) + 2) { mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid fill buffer packet\n"); return 0; } return net_stream_fill_buffer(cl,le2me_16(*((uint16_t*)pack->data))); case NET_STREAM_SEEK: if(pack->len != sizeof(mp_net_stream_packet_t) + 8) { mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid fill buffer packet\n"); return 0; } return net_stream_seek(cl,le2me_64(*((uint64_t*)pack->data))); case NET_STREAM_RESET: return net_stream_reset(cl); case NET_STREAM_CLOSE: if(pack->len != sizeof(mp_net_stream_packet_t)){ mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid fill buffer packet\n"); return 0; } return net_stream_close(cl); default: mp_msg(MSGT_NETST,MSGL_WARN,"Got unknown command %d\n",pack->cmd); if(!write_error(cl->fd,"Unknown command\n")) return 0; } return 0; } static client_t* add_client(client_t *head,int fd) { client_t *new = calloc(1,sizeof(client_t)); new->fd = fd; if(!head) return new; new->next = head; head->prev = new; return new; } static int make_fd_set(fd_set* fds, client_t** _cl, int listen) { int max_fd = listen; client_t *cl = *_cl; FD_ZERO(fds); FD_SET(listen,fds); while(cl) { // Remove this client if(cl->fd < 0) { client_t* f = cl; if(cl->prev) cl->prev->next = cl->next; if(cl->next) cl->next->prev = cl->prev; if(cl->stream) free_stream(cl->stream); if(!cl->prev) // Remove the head *_cl = cl->next; cl = cl->next; free(f); continue; } FD_SET(cl->fd,fds); if(cl->fd > max_fd) max_fd = cl->fd; cl = cl->next; } return max_fd+1; } /// Hack to 'cleanly' exit static int run_server = 1; void exit_sig(int sig) { static int count = 0; sig++; // gcc warning count++; if(count==3) exit(1); if(count > 3) #ifdef __MINGW32__ WSACleanup(); #else kill(getpid(),SIGKILL); #endif run_server = 0; } static int main_loop(int listen_fd) { client_t *clients = NULL,*iter; fd_set fds; signal(SIGTERM,exit_sig); // kill #ifndef __MINGW32__ signal(SIGHUP,exit_sig); // kill -HUP / xterm closed signal(SIGINT,exit_sig); // Interrupt from keyboard signal(SIGQUIT,exit_sig); // Quit from keyboard #endif while(run_server) { int sel_n = make_fd_set(&fds,&clients,listen_fd); int n = select(sel_n,&fds,NULL,NULL,NULL); if(n < 0) { if(errno == EINTR) continue; mp_msg(MSGT_NETST,MSGL_FATAL,"Select error: %s\n",strerror(errno)); return 1; } // New connection if(FD_ISSET(listen_fd,&fds)) { struct sockaddr_in addr; socklen_t slen = sizeof(struct sockaddr_in); int client_fd = accept(listen_fd,(struct sockaddr*)&addr,&slen); if(client_fd < 0) { mp_msg(MSGT_NETST,MSGL_ERR,"accept failed: %s\n",strerror(errno)); continue; } mp_msg(MSGT_NETST,MSGL_V,"New client from %s\n",inet_ntoa(addr.sin_addr)); clients = add_client(clients,client_fd); if(n == 1) continue; } // Look for the clients for(iter = clients ; iter ; iter = iter->next) { mp_net_stream_packet_t* pack; if(!FD_ISSET(iter->fd,&fds)) continue; pack = read_packet(iter->fd); if(!pack) { close(iter->fd); iter->fd = -1; continue; } if(!handle_client(iter,pack)) { close(iter->fd); iter->fd = -1; } free(pack); } } mp_msg(MSGT_NETST,MSGL_INFO,"Exit ....\n"); close(listen_fd); #ifdef __MINGW32__ WSACleanup(); #endif while(clients) { client_t* f = clients; if(f->stream) free_stream(f->stream); if(f->fd > 0) close(f->fd); free(f); clients = clients->next; } return 0; } int main(int argc, char** argv) { int listen_fd; struct sockaddr_in addr; mp_msg_init(); // mp_msg_set_level(verbose+MSGL_STATUS); #ifdef __MINGW32__ WSADATA wsaData; WSAStartup(MAKEWORD(1,1), &wsaData); #endif listen_fd = socket(AF_INET, SOCK_STREAM, 0); if(listen_fd < 0) { mp_msg(MSGT_NETST,MSGL_FATAL,"Failed to create listen_fd: %s\n",strerror(errno)); return -1; } memset(&addr,0,sizeof(struct sockaddr)); addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(port); addr.sin_family = AF_INET; if(bind(listen_fd,(struct sockaddr*)&addr,sizeof(struct sockaddr))) { mp_msg(MSGT_NETST,MSGL_FATAL,"Failed to bind listen socket: %s\n",strerror(errno)); return -1; } if(listen(listen_fd,1)) { mp_msg(MSGT_NETST,MSGL_FATAL,"Failed to turn the socket in listen state: %s\n",strerror(errno)); return -1; } return main_loop(listen_fd); } //---- For libmpdemux float stream_cache_seek_min_percent=50.0; float stream_cache_min_percent=20.0; #include <libmpdemux/demuxer.h> #include <libmpdemux/stheader.h> // audio stream skip/resync functions requires only for seeking. // (they should be implemented in the audio codec layer) void skip_audio_frame(sh_audio_t *sh_audio){ sh_audio=NULL; } void resync_audio_stream(sh_audio_t *sh_audio){ sh_audio=NULL; } int mp_input_check_interrupt(int time){ if(time) usleep(time); return 0; } // for libdvdread: #include "get_path.c" int stream_cache_size=0; // for demux_ogg: void* vo_sub=NULL; int vo_osd_changed(int new_value){ new_value++; return 0;} int subcc_enabled=0; float sub_fps=0; int sub_utf8=0; int suboverlap_enabled = 1; float sub_delay=0; //---------------