mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
ffserver: add stream Metadata option
Also deprecate Author, Comment, Copyright, and Title options, and update docs to use the new Metadata option.
This commit is contained in:
parent
33f10fa657
commit
9985710a5a
@ -235,7 +235,7 @@ StartSendOnKey
|
|||||||
|
|
||||||
#<Stream test.ogg>
|
#<Stream test.ogg>
|
||||||
#Feed feed1.ffm
|
#Feed feed1.ffm
|
||||||
#Title "Stream title"
|
#Metadata title "Stream title"
|
||||||
#AudioBitRate 64
|
#AudioBitRate 64
|
||||||
#AudioChannels 2
|
#AudioChannels 2
|
||||||
#AudioSampleRate 44100
|
#AudioSampleRate 44100
|
||||||
@ -280,10 +280,10 @@ StartSendOnKey
|
|||||||
#<Stream file.asf>
|
#<Stream file.asf>
|
||||||
#File "/usr/local/httpd/htdocs/test.asf"
|
#File "/usr/local/httpd/htdocs/test.asf"
|
||||||
#NoAudio
|
#NoAudio
|
||||||
#Author "Me"
|
#Metadata author "Me"
|
||||||
#Copyright "Super MegaCorp"
|
#Metadata copyright "Super MegaCorp"
|
||||||
#Title "Test stream from disk"
|
#Metadata title "Test stream from disk"
|
||||||
#Comment "Test comment"
|
#Metadata comment "Test comment"
|
||||||
#</Stream>
|
#</Stream>
|
||||||
|
|
||||||
|
|
||||||
|
@ -550,7 +550,11 @@ for regular streams.
|
|||||||
@item Comment @var{value}
|
@item Comment @var{value}
|
||||||
@item Copyright @var{value}
|
@item Copyright @var{value}
|
||||||
@item Title @var{value}
|
@item Title @var{value}
|
||||||
Set metadata corresponding to the option.
|
Set metadata corresponding to the option. All these options are
|
||||||
|
deprecated in favor of @option{Metadata}.
|
||||||
|
|
||||||
|
@item Metadata @var{key} @var{value}
|
||||||
|
Set metadata value on the output stream.
|
||||||
|
|
||||||
@item NoAudio
|
@item NoAudio
|
||||||
@item NoVideo
|
@item NoVideo
|
||||||
@ -757,7 +761,7 @@ Ogg Vorbis audio
|
|||||||
@example
|
@example
|
||||||
<Stream test.ogg>
|
<Stream test.ogg>
|
||||||
Feed feed1.ffm
|
Feed feed1.ffm
|
||||||
Title "Stream title"
|
Metadata title "Stream title"
|
||||||
AudioBitRate 64
|
AudioBitRate 64
|
||||||
AudioChannels 2
|
AudioChannels 2
|
||||||
AudioSampleRate 44100
|
AudioSampleRate 44100
|
||||||
@ -804,10 +808,10 @@ NoAudio
|
|||||||
<Stream file.asf>
|
<Stream file.asf>
|
||||||
File "/usr/local/httpd/htdocs/test.asf"
|
File "/usr/local/httpd/htdocs/test.asf"
|
||||||
NoAudio
|
NoAudio
|
||||||
Author "Me"
|
Metadata author "Me"
|
||||||
Copyright "Super MegaCorp"
|
Metadata copyright "Super MegaCorp"
|
||||||
Title "Test stream from disk"
|
Metadata title "Test stream from disk"
|
||||||
Comment "Test comment"
|
Metadata comment "Test comment"
|
||||||
</Stream>
|
</Stream>
|
||||||
@end example
|
@end example
|
||||||
@end itemize
|
@end itemize
|
||||||
|
60
ffserver.c
60
ffserver.c
@ -216,6 +216,7 @@ typedef struct FFStream {
|
|||||||
struct FFStream *feed; /* feed we are using (can be null if
|
struct FFStream *feed; /* feed we are using (can be null if
|
||||||
coming from file) */
|
coming from file) */
|
||||||
AVDictionary *in_opts; /* input parameters */
|
AVDictionary *in_opts; /* input parameters */
|
||||||
|
AVDictionary *metadata; /* metadata to set on the stream */
|
||||||
AVInputFormat *ifmt; /* if non NULL, force input format */
|
AVInputFormat *ifmt; /* if non NULL, force input format */
|
||||||
AVOutputFormat *fmt;
|
AVOutputFormat *fmt;
|
||||||
IPAddressACL *acl;
|
IPAddressACL *acl;
|
||||||
@ -228,10 +229,6 @@ typedef struct FFStream {
|
|||||||
int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
|
int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
|
||||||
char feed_filename[1024]; /* file name of the feed storage, or
|
char feed_filename[1024]; /* file name of the feed storage, or
|
||||||
input file name for a stream */
|
input file name for a stream */
|
||||||
char author[512];
|
|
||||||
char title[512];
|
|
||||||
char copyright[512];
|
|
||||||
char comment[512];
|
|
||||||
pid_t pid; /* Of ffmpeg process */
|
pid_t pid; /* Of ffmpeg process */
|
||||||
time_t pid_start; /* Of ffmpeg process */
|
time_t pid_start; /* Of ffmpeg process */
|
||||||
char **child_argv;
|
char **child_argv;
|
||||||
@ -2279,11 +2276,7 @@ static int http_prepare_data(HTTPContext *c)
|
|||||||
switch(c->state) {
|
switch(c->state) {
|
||||||
case HTTPSTATE_SEND_DATA_HEADER:
|
case HTTPSTATE_SEND_DATA_HEADER:
|
||||||
memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
|
memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
|
||||||
av_dict_set(&c->fmt_ctx.metadata, "author" , c->stream->author , 0);
|
av_dict_copy(&(c->fmt_ctx.metadata), c->stream->metadata, 0);
|
||||||
av_dict_set(&c->fmt_ctx.metadata, "comment" , c->stream->comment , 0);
|
|
||||||
av_dict_set(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
|
|
||||||
av_dict_set(&c->fmt_ctx.metadata, "title" , c->stream->title , 0);
|
|
||||||
|
|
||||||
c->fmt_ctx.streams = av_mallocz(sizeof(AVStream *) * c->stream->nb_streams);
|
c->fmt_ctx.streams = av_mallocz(sizeof(AVStream *) * c->stream->nb_streams);
|
||||||
|
|
||||||
for(i=0;i<c->stream->nb_streams;i++) {
|
for(i=0;i<c->stream->nb_streams;i++) {
|
||||||
@ -2993,6 +2986,7 @@ static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
|
|||||||
AVFormatContext *avc;
|
AVFormatContext *avc;
|
||||||
AVStream *avs = NULL;
|
AVStream *avs = NULL;
|
||||||
AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
|
AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
|
||||||
|
AVDictionaryEntry *entry = av_dict_get(stream->metadata, "title", NULL, 0);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
avc = avformat_alloc_context();
|
avc = avformat_alloc_context();
|
||||||
@ -3001,7 +2995,7 @@ static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
|
|||||||
}
|
}
|
||||||
avc->oformat = rtp_format;
|
avc->oformat = rtp_format;
|
||||||
av_dict_set(&avc->metadata, "title",
|
av_dict_set(&avc->metadata, "title",
|
||||||
stream->title[0] ? stream->title : "No Title", 0);
|
entry ? entry->value : "No Title", 0);
|
||||||
avc->nb_streams = stream->nb_streams;
|
avc->nb_streams = stream->nb_streams;
|
||||||
if (stream->is_multicast) {
|
if (stream->is_multicast) {
|
||||||
snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
|
snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
|
||||||
@ -4067,7 +4061,7 @@ static int parse_ffconfig(const char *filename)
|
|||||||
FILE *f;
|
FILE *f;
|
||||||
char line[1024];
|
char line[1024];
|
||||||
char cmd[64];
|
char cmd[64];
|
||||||
char arg[1024];
|
char arg[1024], arg2[1024];
|
||||||
const char *p;
|
const char *p;
|
||||||
int val, errors, line_num;
|
int val, errors, line_num;
|
||||||
FFStream **last_stream, *stream, *redirect;
|
FFStream **last_stream, *stream, *redirect;
|
||||||
@ -4367,18 +4361,37 @@ static int parse_ffconfig(const char *filename)
|
|||||||
} else {
|
} else {
|
||||||
ERROR("FaviconURL only permitted for status streams\n");
|
ERROR("FaviconURL only permitted for status streams\n");
|
||||||
}
|
}
|
||||||
} else if (!av_strcasecmp(cmd, "Author")) {
|
} else if (!av_strcasecmp(cmd, "Author") ||
|
||||||
if (stream)
|
!av_strcasecmp(cmd, "Comment") ||
|
||||||
get_arg(stream->author, sizeof(stream->author), &p);
|
!av_strcasecmp(cmd, "Copyright") ||
|
||||||
} else if (!av_strcasecmp(cmd, "Comment")) {
|
!av_strcasecmp(cmd, "Title")) {
|
||||||
if (stream)
|
get_arg(arg, sizeof(arg), &p);
|
||||||
get_arg(stream->comment, sizeof(stream->comment), &p);
|
|
||||||
} else if (!av_strcasecmp(cmd, "Copyright")) {
|
if (stream) {
|
||||||
if (stream)
|
char key[32];
|
||||||
get_arg(stream->copyright, sizeof(stream->copyright), &p);
|
int i, ret;
|
||||||
} else if (!av_strcasecmp(cmd, "Title")) {
|
|
||||||
if (stream)
|
for (i = 0; i < strlen(cmd); i++)
|
||||||
get_arg(stream->title, sizeof(stream->title), &p);
|
key[i] = av_tolower(cmd[i]);
|
||||||
|
key[i] = 0;
|
||||||
|
av_log(NULL, AV_LOG_WARNING,
|
||||||
|
"'%s' option in configuration file is deprecated, "
|
||||||
|
"use 'Metadata %s VALUE' instead\n", cmd, key);
|
||||||
|
if ((ret = av_dict_set(&stream->metadata, key, arg, 0)) < 0) {
|
||||||
|
ERROR("Could not set metadata '%s' to value '%s': %s\n",
|
||||||
|
key, arg, av_err2str(ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!av_strcasecmp(cmd, "Metadata")) {
|
||||||
|
get_arg(arg, sizeof(arg), &p);
|
||||||
|
get_arg(arg2, sizeof(arg2), &p);
|
||||||
|
if (stream) {
|
||||||
|
int ret;
|
||||||
|
if ((ret = av_dict_set(&stream->metadata, arg, arg2, 0)) < 0) {
|
||||||
|
ERROR("Could not set metadata '%s' to value '%s': %s\n",
|
||||||
|
arg, arg2, av_err2str(ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (!av_strcasecmp(cmd, "Preroll")) {
|
} else if (!av_strcasecmp(cmd, "Preroll")) {
|
||||||
get_arg(arg, sizeof(arg), &p);
|
get_arg(arg, sizeof(arg), &p);
|
||||||
if (stream)
|
if (stream)
|
||||||
@ -4501,7 +4514,6 @@ static int parse_ffconfig(const char *filename)
|
|||||||
}
|
}
|
||||||
} else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
|
} else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
|
||||||
!av_strcasecmp(cmd, "AVOptionAudio")) {
|
!av_strcasecmp(cmd, "AVOptionAudio")) {
|
||||||
char arg2[1024];
|
|
||||||
AVCodecContext *avctx;
|
AVCodecContext *avctx;
|
||||||
int type;
|
int type;
|
||||||
get_arg(arg, sizeof(arg), &p);
|
get_arg(arg, sizeof(arg), &p);
|
||||||
|
Loading…
Reference in New Issue
Block a user