summaryrefslogtreecommitdiff
path: root/ffserver.c
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2002-11-20 20:49:47 +0000
committerFabrice Bellard <fabrice@bellard.org>2002-11-20 20:49:47 +0000
commit0fa45e19cebfc7ff078d6ce1749cc851577e688b (patch)
tree67eb4440803d38013914be80ef2c379c3d5626ec /ffserver.c
parent6891b9d458e49c3de6b87dfc48f54891629902b8 (diff)
minimum handling for mpeg4 video multicast from avi files
Originally committed as revision 1262 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'ffserver.c')
-rw-r--r--ffserver.c89
1 files changed, 85 insertions, 4 deletions
diff --git a/ffserver.c b/ffserver.c
index a9250cad31..8a55af9b17 100644
--- a/ffserver.c
+++ b/ffserver.c
@@ -482,9 +482,9 @@ static void start_multicast(void)
dest_addr.sin_port = htons(stream->multicast_port +
2 * stream_index);
if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr) < 0) {
- fprintf(stderr, "Could not open input stream %d for stream '%s'\n",
- stream_index, stream->filename);
- continue;
+ fprintf(stderr, "Could not open output stream '%s/streamid=%d'\n",
+ stream->filename, stream_index);
+ exit(1);
}
}
@@ -2605,7 +2605,7 @@ static int prepare_sdp_description(FFStream *stream, UINT8 **pbuffer,
struct in_addr my_ip)
{
ByteIOContext pb1, *pb = &pb1;
- int i, payload_type, port;
+ int i, payload_type, port, private_payload_type, j;
const char *ipstr, *title, *mediatype;
AVStream *st;
@@ -2627,6 +2627,7 @@ static int prepare_sdp_description(FFStream *stream, UINT8 **pbuffer,
url_fprintf(pb, "c=IN IP4 %s\n", inet_ntoa(stream->multicast_ip));
}
/* for each stream, we output the necessary info */
+ private_payload_type = 96;
for(i = 0; i < stream->nb_streams; i++) {
st = stream->streams[i];
switch(st->codec.codec_type) {
@@ -2643,6 +2644,8 @@ static int prepare_sdp_description(FFStream *stream, UINT8 **pbuffer,
/* NOTE: the port indication is not correct in case of
unicast. It is not an issue because RTSP gives it */
payload_type = rtp_get_payload_type(&st->codec);
+ if (payload_type < 0)
+ payload_type = private_payload_type++;
if (stream->is_multicast) {
port = stream->multicast_port + 2 * i;
} else {
@@ -2650,9 +2653,37 @@ static int prepare_sdp_description(FFStream *stream, UINT8 **pbuffer,
}
url_fprintf(pb, "m=%s %d RTP/AVP %d\n",
mediatype, port, payload_type);
+ if (payload_type >= 96) {
+ /* for private payload type, we need to give more info */
+ switch(st->codec.codec_id) {
+ case CODEC_ID_MPEG4:
+ {
+ uint8_t *data;
+ url_fprintf(pb, "a=rtpmap:%d MP4V-ES/%d\n",
+ payload_type, 90000);
+ /* we must also add the mpeg4 header */
+ data = st->codec.extradata;
+ if (data) {
+ url_fprintf(pb, "a=fmtp:%d config=");
+ for(j=0;j<st->codec.extradata_size;j++) {
+ url_fprintf(pb, "%02x", data[j]);
+ }
+ url_fprintf(pb, "\n");
+ }
+ }
+ break;
+ default:
+ /* XXX: add other codecs ? */
+ goto fail;
+ }
+ }
url_fprintf(pb, "a=control:streamid=%d\n", i);
}
return url_close_dyn_buf(pb, pbuffer);
+ fail:
+ url_close_dyn_buf(pb, pbuffer);
+ av_free(*pbuffer);
+ return -1;
}
static void rtsp_cmd_describe(HTTPContext *c, const char *url)
@@ -3183,6 +3214,54 @@ void remove_stream(FFStream *stream)
}
}
+/* specific mpeg4 handling : we extract the raw parameters */
+void extract_mpeg4_header(AVFormatContext *infile)
+{
+ int mpeg4_count, i, size;
+ AVPacket pkt;
+ AVStream *st;
+ const UINT8 *p;
+
+ mpeg4_count = 0;
+ for(i=0;i<infile->nb_streams;i++) {
+ st = infile->streams[i];
+ if (st->codec.codec_id == CODEC_ID_MPEG4 &&
+ st->codec.extradata == NULL) {
+ mpeg4_count++;
+ }
+ }
+ if (!mpeg4_count)
+ return;
+
+ printf("MPEG4 without extra data: trying to find header\n");
+ while (mpeg4_count > 0) {
+ if (av_read_packet(infile, &pkt) < 0)
+ break;
+ st = infile->streams[pkt.stream_index];
+ if (st->codec.codec_id == CODEC_ID_MPEG4 &&
+ st->codec.extradata == NULL) {
+ /* fill extradata with the header */
+ /* XXX: we make hard suppositions here ! */
+ p = pkt.data;
+ while (p < pkt.data + pkt.size - 4) {
+ /* stop when vop header is found */
+ if (p[0] == 0x00 && p[1] == 0x00 &&
+ p[2] == 0x01 && p[3] == 0xb6) {
+ size = p - pkt.data;
+ // av_hex_dump(pkt.data, size);
+ st->codec.extradata = av_malloc(size);
+ st->codec.extradata_size = size;
+ memcpy(st->codec.extradata, pkt.data, size);
+ break;
+ }
+ p++;
+ }
+ mpeg4_count--;
+ }
+ av_free_packet(&pkt);
+ }
+}
+
/* compute the needed AVStream for each file */
void build_file_streams(void)
{
@@ -3213,6 +3292,8 @@ void build_file_streams(void)
av_close_input_file(infile);
goto fail;
}
+ extract_mpeg4_header(infile);
+
for(i=0;i<infile->nb_streams;i++) {
add_av_stream1(stream, &infile->streams[i]->codec);
}