AV_WB24(out, 1);
- if(c->codec_id == CODEC_ID_MPEG4){
+ if(c->codec_id == AV_CODEC_ID_MPEG4){
if(key_frame){
return 3;
}else{
out[3]= 0xB6;
return 4;
}
- }else if(c->codec_id == CODEC_ID_MPEG1VIDEO || c->codec_id == CODEC_ID_MPEG2VIDEO){
+ }else if(c->codec_id == AV_CODEC_ID_MPEG1VIDEO || c->codec_id == AV_CODEC_ID_MPEG2VIDEO){
return 3;
- }else if(c->codec_id == CODEC_ID_H264){
+ }else if(c->codec_id == AV_CODEC_ID_H264){
return 3;
- }else if(c->codec_id == CODEC_ID_MP3 || c->codec_id == CODEC_ID_MP2){
+ }else if(c->codec_id == AV_CODEC_ID_MP3 || c->codec_id == AV_CODEC_ID_MP2){
int lsf, mpeg25, sample_rate_index, bitrate_index, frame_size;
- int layer= c->codec_id == CODEC_ID_MP3 ? 3 : 2;
+ int layer= c->codec_id == AV_CODEC_ID_MP3 ? 3 : 2;
unsigned int header= 0xFFF00000;
lsf = sample_rate < (24000+32000)/2;
pred_table[2]=1;
pred_table[3]=3;
pred_table[4]=4;
- }else if(codec->codec_id == CODEC_ID_VORBIS){
+ }else if(codec->codec_id == AV_CODEC_ID_VORBIS){
pred_count=3;
pred_table[0]=2;
pred_table[1]=9;
static int write_streaminfo(NUTContext *nut, AVIOContext *bc, int stream_id){
AVFormatContext *s= nut->avf;
AVStream* st = s->streams[stream_id];
+ AVDictionaryEntry *t = NULL;
AVIOContext *dyn_bc;
uint8_t *dyn_buf=NULL;
int count=0, dyn_size, i;
if(ret < 0)
return ret;
+ while ((t = av_dict_get(st->metadata, "", t, AV_DICT_IGNORE_SUFFIX)))
+ count += add_info(dyn_bc, t->key, t->value);
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);
return 0;
}
+static int write_index(NUTContext *nut, AVIOContext *bc){
+ int i;
+ Syncpoint dummy= { .pos= 0 };
+ Syncpoint *next_node[2] = { NULL };
+ int64_t startpos = avio_tell(bc);
+ int64_t payload_size;
+
+ put_tt(nut, nut->max_pts_tb, bc, nut->max_pts);
+
+ ff_put_v(bc, nut->sp_count);
+
+ for(i=0; i<nut->sp_count; i++){
+ av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp, (void**)next_node);
+ ff_put_v(bc, (next_node[1]->pos >> 4) - (dummy.pos>>4));
+ dummy.pos = next_node[1]->pos;
+ }
+
+ for(i=0; i<nut->avf->nb_streams; i++){
+ StreamContext *nus= &nut->stream[i];
+ int64_t last_pts= -1;
+ int j, k;
+ for(j=0; j<nut->sp_count; j++){
+ int flag = (nus->keyframe_pts[j] != AV_NOPTS_VALUE) ^ (j+1 == nut->sp_count);
+ int n = 0;
+ for(; j<nut->sp_count && (nus->keyframe_pts[j] != AV_NOPTS_VALUE) == flag; j++)
+ n++;
+
+ ff_put_v(bc, 1 + 2*flag + 4*n);
+ for(k= j - n; k<=j && k<nut->sp_count; k++) {
+ if(nus->keyframe_pts[k] == AV_NOPTS_VALUE)
+ continue;
+ av_assert0(nus->keyframe_pts[k] > last_pts);
+ ff_put_v(bc, nus->keyframe_pts[k] - last_pts);
+ last_pts = nus->keyframe_pts[k];
+ }
+ }
+ }
+
+ payload_size = avio_tell(bc) - startpos + 8 + 4;
+
+ avio_wb64(bc, 8 + payload_size + av_log2(payload_size) / 7 + 1 + 4*(payload_size > 4096));
+
+ return 0;
+}
+
static int write_headers(AVFormatContext *avctx, AVIOContext *bc){
NUTContext *nut = avctx->priv_data;
AVIOContext *dyn_bc;
int store_sp=0;
int ret;
- if(pkt->pts < 0)
- return -1;
+ if (pkt->pts < 0) {
+ av_log(s, AV_LOG_ERROR, "Invalid negative packet pts %"PRId64" in input\n", pkt->pts);
+ return AVERROR(EINVAL);
+ }
if(1LL<<(20+3*nut->header_count) <= avio_tell(bc))
write_headers(s, bc);
put_packet(nut, bc, dyn_bc, 1, SYNCPOINT_STARTCODE);
ff_nut_add_sp(nut, nut->last_syncpoint_pos, 0/*unused*/, pkt->dts);
+
+ if((1ll<<60) % nut->sp_count == 0)
+ for(i=0; i<s->nb_streams; i++){
+ int j;
+ StreamContext *nus = &nut->stream[i];
+ nus->keyframe_pts = av_realloc(nus->keyframe_pts, 2*nut->sp_count*sizeof(*nus->keyframe_pts));
+ if(!nus->keyframe_pts)
+ return AVERROR(ENOMEM);
+ for(j=nut->sp_count == 1 ? 0 : nut->sp_count; j<2*nut->sp_count; j++)
+ nus->keyframe_pts[j] = AV_NOPTS_VALUE;
+ }
}
av_assert0(nus->last_pts != AV_NOPTS_VALUE);
nus->last_pts= pkt->pts;
//FIXME just store one per syncpoint
- if(flags & FLAG_KEY)
+ if(flags & FLAG_KEY) {
av_add_index_entry(
s->streams[pkt->stream_index],
nut->last_syncpoint_pos,
0,
0,
AVINDEX_KEYFRAME);
+ if(nus->keyframe_pts && nus->keyframe_pts[nut->sp_count] == AV_NOPTS_VALUE)
+ nus->keyframe_pts[nut->sp_count] = pkt->pts;
+ }
+
+ if(!nut->max_pts_tb || av_compare_ts(nut->max_pts, *nut->max_pts_tb, pkt->pts, *nus->time_base) < 0) {
+ nut->max_pts = pkt->pts;
+ nut->max_pts_tb = nus->time_base;
+ }
return 0;
}
static int nut_write_trailer(AVFormatContext *s){
NUTContext *nut= s->priv_data;
- AVIOContext *bc= s->pb;
+ AVIOContext *bc = s->pb, *dyn_bc;
+ int i, ret;
while(nut->header_count<3)
write_headers(s, bc);
+
+ ret = avio_open_dyn_buf(&dyn_bc);
+ if(ret >= 0) {
+ write_index(nut, dyn_bc);
+ put_packet(nut, bc, dyn_bc, 1, INDEX_STARTCODE);
+ }
+
avio_flush(bc);
ff_nut_free_sp(nut);
+ for(i=0; i<s->nb_streams; i++)
+ av_freep(&nut->stream[i].keyframe_pts);
+
av_freep(&nut->stream);
av_freep(&nut->chapter);
av_freep(&nut->time_base);
AVOutputFormat ff_nut_muxer = {
.name = "nut",
- .long_name = NULL_IF_CONFIG_SMALL("NUT format"),
+ .long_name = NULL_IF_CONFIG_SMALL("NUT"),
.mime_type = "video/x-nut",
.extensions = "nut",
.priv_data_size = sizeof(NUTContext),
-#if CONFIG_LIBVORBIS
- .audio_codec = CODEC_ID_VORBIS,
-#elif CONFIG_LIBMP3LAME
- .audio_codec = CODEC_ID_MP3,
-#else
- .audio_codec = CODEC_ID_MP2,
-#endif
- .video_codec = CODEC_ID_MPEG4,
+ .audio_codec = CONFIG_LIBVORBIS ? AV_CODEC_ID_VORBIS :
+ CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_MP2,
+ .video_codec = AV_CODEC_ID_MPEG4,
.write_header = nut_write_header,
.write_packet = nut_write_packet,
.write_trailer = nut_write_trailer,