Commit 90c2295b authored by Evgeniy Stepanov's avatar Evgeniy Stepanov

Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing

of matroska and nut.

Originally committed as revision 12358 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent b049ad50
...@@ -1592,6 +1592,8 @@ static int av_encode(AVFormatContext **output_files, ...@@ -1592,6 +1592,8 @@ static int av_encode(AVFormatContext **output_files,
av_strlcpy(ost->st->language, ist->st->language, av_strlcpy(ost->st->language, ist->st->language,
sizeof(ost->st->language)); sizeof(ost->st->language));
ost->st->disposition = ist->st->disposition;
if (ost->st->stream_copy) { if (ost->st->stream_copy) {
/* if stream_copy is selected, no need to decode or encode */ /* if stream_copy is selected, no need to decode or encode */
codec->codec_id = icodec->codec_id; codec->codec_id = icodec->codec_id;
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#define FFMPEG_AVFORMAT_H #define FFMPEG_AVFORMAT_H
#define LIBAVFORMAT_VERSION_MAJOR 52 #define LIBAVFORMAT_VERSION_MAJOR 52
#define LIBAVFORMAT_VERSION_MINOR 7 #define LIBAVFORMAT_VERSION_MINOR 8
#define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_MICRO 0
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
...@@ -278,6 +278,13 @@ typedef struct AVIndexEntry { ...@@ -278,6 +278,13 @@ typedef struct AVIndexEntry {
int min_distance; /**< min distance between this and the previous keyframe, used to avoid unneeded searching */ int min_distance; /**< min distance between this and the previous keyframe, used to avoid unneeded searching */
} AVIndexEntry; } AVIndexEntry;
#define AV_DISPOSITION_DEFAULT 0x0001
#define AV_DISPOSITION_DUB 0x0002
#define AV_DISPOSITION_ORIGINAL 0x0004
#define AV_DISPOSITION_COMMENT 0x0008
#define AV_DISPOSITION_LYRICS 0x0010
#define AV_DISPOSITION_KARAOKE 0x0020
/** /**
* Stream structure. * Stream structure.
* New fields can be added to the end with minor version bumps. * New fields can be added to the end with minor version bumps.
...@@ -357,6 +364,8 @@ typedef struct AVStream { ...@@ -357,6 +364,8 @@ typedef struct AVStream {
int64_t pts_buffer[MAX_REORDER_DELAY+1]; int64_t pts_buffer[MAX_REORDER_DELAY+1];
char *filename; /**< source filename of the stream */ char *filename; /**< source filename of the stream */
int disposition; /**< AV_DISPOSITION_* bitfield */
} AVStream; } AVStream;
#define AV_PROGRAM_RUNNING 1 #define AV_PROGRAM_RUNNING 1
......
...@@ -2298,6 +2298,9 @@ matroska_read_header (AVFormatContext *s, ...@@ -2298,6 +2298,9 @@ matroska_read_header (AVFormatContext *s,
if (strcmp(track->language, "und")) if (strcmp(track->language, "und"))
strcpy(st->language, track->language); strcpy(st->language, track->language);
if (track->flags & MATROSKA_TRACK_DEFAULT)
st->disposition |= AV_DISPOSITION_DEFAULT;
if (track->default_duration) if (track->default_duration)
av_reduce(&st->codec->time_base.num, &st->codec->time_base.den, av_reduce(&st->codec->time_base.num, &st->codec->time_base.den,
track->default_duration, 1000000000, 30000); track->default_duration, 1000000000, 30000);
......
...@@ -550,6 +550,8 @@ static int mkv_write_tracks(AVFormatContext *s) ...@@ -550,6 +550,8 @@ static int mkv_write_tracks(AVFormatContext *s)
else else
put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, "und"); put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, "und");
put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGDEFAULT, !!(st->disposition & AV_DISPOSITION_DEFAULT));
// look for a codec ID string specific to mkv to use, // look for a codec ID string specific to mkv to use,
// if none are found, use AVI codes // if none are found, use AVI codes
for (j = 0; ff_mkv_codec_tags[j].id != CODEC_ID_NONE; j++) { for (j = 0; ff_mkv_codec_tags[j].id != CODEC_ID_NONE; j++) {
......
...@@ -68,3 +68,14 @@ void ff_nut_add_sp(NUTContext *nut, int64_t pos, int64_t back_ptr, int64_t ts){ ...@@ -68,3 +68,14 @@ void ff_nut_add_sp(NUTContext *nut, int64_t pos, int64_t back_ptr, int64_t ts){
av_free(node); av_free(node);
} }
} }
const Dispositions ff_nut_dispositions[] = {
{"default" , AV_DISPOSITION_DEFAULT},
{"dub" , AV_DISPOSITION_DUB},
{"original" , AV_DISPOSITION_ORIGINAL},
{"comment" , AV_DISPOSITION_COMMENT},
{"lyrics" , AV_DISPOSITION_LYRICS},
{"karaoke" , AV_DISPOSITION_KARAOKE},
{"" , 0}
};
...@@ -99,10 +99,17 @@ typedef struct { ...@@ -99,10 +99,17 @@ typedef struct {
extern const AVCodecTag ff_nut_subtitle_tags[]; extern const AVCodecTag ff_nut_subtitle_tags[];
typedef struct {
char str[9];
int flag;
} Dispositions;
void ff_nut_reset_ts(NUTContext *nut, AVRational time_base, int64_t val); void ff_nut_reset_ts(NUTContext *nut, AVRational time_base, int64_t val);
int64_t ff_lsb2full(StreamContext *stream, int64_t lsb); int64_t ff_lsb2full(StreamContext *stream, int64_t lsb);
int ff_nut_sp_pos_cmp(syncpoint_t *a, syncpoint_t *b); int ff_nut_sp_pos_cmp(syncpoint_t *a, syncpoint_t *b);
int ff_nut_sp_pts_cmp(syncpoint_t *a, syncpoint_t *b); int ff_nut_sp_pts_cmp(syncpoint_t *a, syncpoint_t *b);
void ff_nut_add_sp(NUTContext *nut, int64_t pos, int64_t back_ptr, int64_t ts); void ff_nut_add_sp(NUTContext *nut, int64_t pos, int64_t back_ptr, int64_t ts);
extern const Dispositions ff_nut_dispositions[];
#endif /* FFMPEG_NUT_H */ #endif /* FFMPEG_NUT_H */
...@@ -371,6 +371,19 @@ static int decode_stream_header(NUTContext *nut){ ...@@ -371,6 +371,19 @@ static int decode_stream_header(NUTContext *nut){
return 0; return 0;
} }
static void set_disposition_bits(AVFormatContext* avf, char* value, int stream_id){
int flag = 0, i;
for (i=0; ff_nut_dispositions[i].flag; ++i) {
if (!strcmp(ff_nut_dispositions[i].str, value))
flag = ff_nut_dispositions[i].flag;
}
if (!flag)
av_log(avf, AV_LOG_INFO, "unknown disposition type '%s'\n", value);
for (i = 0; i < avf->nb_streams; ++i)
if (stream_id == i || stream_id == -1)
avf->streams[i]->disposition |= flag;
}
static int decode_info_header(NUTContext *nut){ static int decode_info_header(NUTContext *nut){
AVFormatContext *s= nut->avf; AVFormatContext *s= nut->avf;
ByteIOContext *bc = s->pb; ByteIOContext *bc = s->pb;
...@@ -412,6 +425,11 @@ static int decode_info_header(NUTContext *nut){ ...@@ -412,6 +425,11 @@ static int decode_info_header(NUTContext *nut){
type= "v"; type= "v";
} }
if (stream_id_plus1 < 0 || stream_id_plus1 > s->nb_streams) {
av_log(s, AV_LOG_ERROR, "invalid stream id for info packet\n");
continue;
}
if(chapter_id==0 && !strcmp(type, "UTF-8")){ if(chapter_id==0 && !strcmp(type, "UTF-8")){
if (!strcmp(name, "Author")) if (!strcmp(name, "Author"))
av_strlcpy(s->author , str_value, sizeof(s->author)); av_strlcpy(s->author , str_value, sizeof(s->author));
...@@ -421,6 +439,8 @@ static int decode_info_header(NUTContext *nut){ ...@@ -421,6 +439,8 @@ static int decode_info_header(NUTContext *nut){
av_strlcpy(s->copyright, str_value, sizeof(s->copyright)); av_strlcpy(s->copyright, str_value, sizeof(s->copyright));
else if(!strcmp(name, "Description")) else if(!strcmp(name, "Description"))
av_strlcpy(s->comment , str_value, sizeof(s->comment)); av_strlcpy(s->comment , str_value, sizeof(s->comment));
else if(!strcmp(name, "Disposition"))
set_disposition_bits(s, str_value, stream_id_plus1 - 1);
} }
} }
......
...@@ -472,6 +472,37 @@ static int write_globalinfo(NUTContext *nut, ByteIOContext *bc){ ...@@ -472,6 +472,37 @@ static int write_globalinfo(NUTContext *nut, ByteIOContext *bc){
return 0; return 0;
} }
static int write_streaminfo(NUTContext *nut, ByteIOContext *bc, int stream_id){
AVFormatContext *s= nut->avf;
AVStream* st = s->streams[stream_id];
ByteIOContext *dyn_bc;
uint8_t *dyn_buf=NULL;
int count=0, dyn_size, i;
int ret = url_open_dyn_buf(&dyn_bc);
if(ret < 0)
return ret;
for (i=0; ff_nut_dispositions[i].flag; ++i) {
if (st->disposition & ff_nut_dispositions[i].flag)
count += add_info(dyn_bc, "Disposition", ff_nut_dispositions[i].str);
}
dyn_size = url_close_dyn_buf(dyn_bc, &dyn_buf);
if (count) {
put_v(bc, stream_id + 1); //stream_id_plus1
put_v(bc, 0); //chapter_id
put_v(bc, 0); //timestamp_start
put_v(bc, 0); //length
put_v(bc, count);
put_buffer(bc, dyn_buf, dyn_size);
}
av_free(dyn_buf);
return count;
}
static int write_headers(NUTContext *nut, ByteIOContext *bc){ static int write_headers(NUTContext *nut, ByteIOContext *bc){
ByteIOContext *dyn_bc; ByteIOContext *dyn_bc;
int i, ret; int i, ret;
...@@ -498,6 +529,22 @@ static int write_headers(NUTContext *nut, ByteIOContext *bc){ ...@@ -498,6 +529,22 @@ static int write_headers(NUTContext *nut, ByteIOContext *bc){
write_globalinfo(nut, dyn_bc); write_globalinfo(nut, dyn_bc);
put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE); put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE);
for (i = 0; i < nut->avf->nb_streams; i++) {
ret = url_open_dyn_buf(&dyn_bc);
if(ret < 0)
return ret;
ret = write_streaminfo(nut, dyn_bc, i);
if (ret < 0)
return ret;
if (ret > 0)
put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE);
else {
uint8_t* buf;
url_close_dyn_buf(dyn_bc, &buf);
av_free(buf);
}
}
nut->last_syncpoint_pos= INT_MIN; nut->last_syncpoint_pos= INT_MIN;
nut->header_count++; nut->header_count++;
return 0; return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment