Skip to content
Snippets Groups Projects
Commit 0fa45e19 authored by Fabrice Bellard's avatar Fabrice Bellard
Browse files

minimum handling for mpeg4 video multicast from avi files

Originally committed as revision 1262 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 6891b9d4
No related branches found
No related tags found
No related merge requests found
...@@ -482,9 +482,9 @@ static void start_multicast(void) ...@@ -482,9 +482,9 @@ static void start_multicast(void)
dest_addr.sin_port = htons(stream->multicast_port + dest_addr.sin_port = htons(stream->multicast_port +
2 * stream_index); 2 * stream_index);
if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr) < 0) { if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr) < 0) {
fprintf(stderr, "Could not open input stream %d for stream '%s'\n", fprintf(stderr, "Could not open output stream '%s/streamid=%d'\n",
stream_index, stream->filename); stream->filename, stream_index);
continue; exit(1);
} }
} }
...@@ -2605,7 +2605,7 @@ static int prepare_sdp_description(FFStream *stream, UINT8 **pbuffer, ...@@ -2605,7 +2605,7 @@ static int prepare_sdp_description(FFStream *stream, UINT8 **pbuffer,
struct in_addr my_ip) struct in_addr my_ip)
{ {
ByteIOContext pb1, *pb = &pb1; ByteIOContext pb1, *pb = &pb1;
int i, payload_type, port; int i, payload_type, port, private_payload_type, j;
const char *ipstr, *title, *mediatype; const char *ipstr, *title, *mediatype;
AVStream *st; AVStream *st;
...@@ -2627,6 +2627,7 @@ static int prepare_sdp_description(FFStream *stream, UINT8 **pbuffer, ...@@ -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)); url_fprintf(pb, "c=IN IP4 %s\n", inet_ntoa(stream->multicast_ip));
} }
/* for each stream, we output the necessary info */ /* for each stream, we output the necessary info */
private_payload_type = 96;
for(i = 0; i < stream->nb_streams; i++) { for(i = 0; i < stream->nb_streams; i++) {
st = stream->streams[i]; st = stream->streams[i];
switch(st->codec.codec_type) { switch(st->codec.codec_type) {
...@@ -2643,6 +2644,8 @@ static int prepare_sdp_description(FFStream *stream, UINT8 **pbuffer, ...@@ -2643,6 +2644,8 @@ static int prepare_sdp_description(FFStream *stream, UINT8 **pbuffer,
/* NOTE: the port indication is not correct in case of /* NOTE: the port indication is not correct in case of
unicast. It is not an issue because RTSP gives it */ unicast. It is not an issue because RTSP gives it */
payload_type = rtp_get_payload_type(&st->codec); payload_type = rtp_get_payload_type(&st->codec);
if (payload_type < 0)
payload_type = private_payload_type++;
if (stream->is_multicast) { if (stream->is_multicast) {
port = stream->multicast_port + 2 * i; port = stream->multicast_port + 2 * i;
} else { } else {
...@@ -2650,9 +2653,37 @@ static int prepare_sdp_description(FFStream *stream, UINT8 **pbuffer, ...@@ -2650,9 +2653,37 @@ static int prepare_sdp_description(FFStream *stream, UINT8 **pbuffer,
} }
url_fprintf(pb, "m=%s %d RTP/AVP %d\n", url_fprintf(pb, "m=%s %d RTP/AVP %d\n",
mediatype, port, payload_type); 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); url_fprintf(pb, "a=control:streamid=%d\n", i);
} }
return url_close_dyn_buf(pb, pbuffer); 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) static void rtsp_cmd_describe(HTTPContext *c, const char *url)
...@@ -3183,6 +3214,54 @@ void remove_stream(FFStream *stream) ...@@ -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 */ /* compute the needed AVStream for each file */
void build_file_streams(void) void build_file_streams(void)
{ {
...@@ -3213,6 +3292,8 @@ void build_file_streams(void) ...@@ -3213,6 +3292,8 @@ void build_file_streams(void)
av_close_input_file(infile); av_close_input_file(infile);
goto fail; goto fail;
} }
extract_mpeg4_header(infile);
for(i=0;i<infile->nb_streams;i++) { for(i=0;i<infile->nb_streams;i++) {
add_av_stream1(stream, &infile->streams[i]->codec); add_av_stream1(stream, &infile->streams[i]->codec);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment