nut->frame_code['N'].flags = FLAG_INVALID;
}
+/**
+ * Get the length in bytes which is needed to store val as v.
+ */
+static int get_v_length(uint64_t val)
+{
+ int i = 1;
+
+ while (val >>= 7)
+ i++;
+
+ return i;
+}
+
+/**
+ * Put val using a variable number of bytes.
+ */
+static void put_v(AVIOContext *bc, uint64_t val)
+{
+ int i = get_v_length(val);
+
+ while (--i > 0)
+ avio_w8(bc, 128 | (uint8_t)(val >> (7*i)));
+
+ avio_w8(bc, val & 127);
+}
+
static void put_tt(NUTContext *nut, AVRational *time_base, AVIOContext *bc, uint64_t val)
{
val *= nut->time_base_count;
val += time_base - nut->time_base;
- ff_put_v(bc, val);
+ put_v(bc, val);
}
/**
* Store a string as vb.
{
size_t len = strlen(string);
- ff_put_v(bc, len);
+ put_v(bc, len);
avio_write(bc, string, len);
}
static void put_s(AVIOContext *bc, int64_t val)
{
- ff_put_v(bc, 2 * FFABS(val) - (val > 0));
+ put_v(bc, 2 * FFABS(val) - (val > 0));
}
-//FIXME remove calculate_checksum
static void put_packet(NUTContext *nut, AVIOContext *bc, AVIOContext *dyn_bc,
- int calculate_checksum, uint64_t startcode)
+ uint64_t startcode)
{
uint8_t *dyn_buf = NULL;
- int dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
- int forw_ptr = dyn_size + 4 * calculate_checksum;
+ int dyn_size = avio_get_dyn_buf(dyn_bc, &dyn_buf);
+ int forw_ptr = dyn_size + 4;
if (forw_ptr > 4096)
ffio_init_checksum(bc, ff_crc04C11DB7_update, 0);
avio_wb64(bc, startcode);
- ff_put_v(bc, forw_ptr);
+ put_v(bc, forw_ptr);
if (forw_ptr > 4096)
avio_wl32(bc, ffio_get_checksum(bc));
- if (calculate_checksum)
- ffio_init_checksum(bc, ff_crc04C11DB7_update, 0);
+ ffio_init_checksum(bc, ff_crc04C11DB7_update, 0);
avio_write(bc, dyn_buf, dyn_size);
- if (calculate_checksum)
- avio_wl32(bc, ffio_get_checksum(bc));
+ avio_wl32(bc, ffio_get_checksum(bc));
- av_free(dyn_buf);
+ ffio_reset_dyn_buf(dyn_bc);
}
static void write_mainheader(NUTContext *nut, AVIOContext *bc)
tmp_head_idx;
int64_t tmp_match;
- ff_put_v(bc, nut->version);
+ put_v(bc, nut->version);
if (nut->version > 3)
- ff_put_v(bc, nut->minor_version = 1);
- ff_put_v(bc, nut->avf->nb_streams);
- ff_put_v(bc, nut->max_distance);
- ff_put_v(bc, nut->time_base_count);
+ put_v(bc, nut->minor_version = 1);
+ put_v(bc, nut->avf->nb_streams);
+ put_v(bc, nut->max_distance);
+ put_v(bc, nut->time_base_count);
for (i = 0; i < nut->time_base_count; i++) {
- ff_put_v(bc, nut->time_base[i].num);
- ff_put_v(bc, nut->time_base[i].den);
+ put_v(bc, nut->time_base[i].num);
+ put_v(bc, nut->time_base[i].den);
}
tmp_pts = 0;
if (j != tmp_mul - tmp_size)
tmp_fields = 6;
- ff_put_v(bc, tmp_flags);
- ff_put_v(bc, tmp_fields);
+ put_v(bc, tmp_flags);
+ put_v(bc, tmp_fields);
if (tmp_fields > 0) put_s(bc, tmp_pts);
- if (tmp_fields > 1) ff_put_v(bc, tmp_mul);
- if (tmp_fields > 2) ff_put_v(bc, tmp_stream);
- if (tmp_fields > 3) ff_put_v(bc, tmp_size);
- if (tmp_fields > 4) ff_put_v(bc, 0 /*tmp_res*/);
- if (tmp_fields > 5) ff_put_v(bc, j);
- if (tmp_fields > 6) ff_put_v(bc, tmp_match);
- if (tmp_fields > 7) ff_put_v(bc, tmp_head_idx);
+ if (tmp_fields > 1) put_v(bc, tmp_mul);
+ if (tmp_fields > 2) put_v(bc, tmp_stream);
+ if (tmp_fields > 3) put_v(bc, tmp_size);
+ if (tmp_fields > 4) put_v(bc, 0 /*tmp_res*/);
+ if (tmp_fields > 5) put_v(bc, j);
+ if (tmp_fields > 6) put_v(bc, tmp_match);
+ if (tmp_fields > 7) put_v(bc, tmp_head_idx);
}
- ff_put_v(bc, nut->header_count - 1);
+ put_v(bc, nut->header_count - 1);
for (i = 1; i < nut->header_count; i++) {
- ff_put_v(bc, nut->header_len[i]);
+ put_v(bc, nut->header_len[i]);
avio_write(bc, nut->header[i], nut->header_len[i]);
}
// flags had been effectively introduced in version 4
if (nut->version > 3)
- ff_put_v(bc, nut->flags);
+ put_v(bc, nut->flags);
}
static int write_streamheader(AVFormatContext *avctx, AVIOContext *bc,
NUTContext *nut = avctx->priv_data;
AVCodecParameters *par = st->codecpar;
- ff_put_v(bc, i);
+ put_v(bc, i);
switch (par->codec_type) {
- case AVMEDIA_TYPE_VIDEO: ff_put_v(bc, 0); break;
- case AVMEDIA_TYPE_AUDIO: ff_put_v(bc, 1); break;
- case AVMEDIA_TYPE_SUBTITLE: ff_put_v(bc, 2); break;
- default: ff_put_v(bc, 3); break;
+ case AVMEDIA_TYPE_VIDEO: put_v(bc, 0); break;
+ case AVMEDIA_TYPE_AUDIO: put_v(bc, 1); break;
+ case AVMEDIA_TYPE_SUBTITLE: put_v(bc, 2); break;
+ default: put_v(bc, 3); break;
}
- ff_put_v(bc, 4);
+ put_v(bc, 4);
if (par->codec_tag) {
avio_wl32(bc, par->codec_tag);
return AVERROR(EINVAL);
}
- ff_put_v(bc, nut->stream[i].time_base - nut->time_base);
- ff_put_v(bc, nut->stream[i].msb_pts_shift);
- ff_put_v(bc, nut->stream[i].max_pts_distance);
- ff_put_v(bc, par->video_delay);
+ put_v(bc, nut->stream[i].time_base - nut->time_base);
+ put_v(bc, nut->stream[i].msb_pts_shift);
+ put_v(bc, nut->stream[i].max_pts_distance);
+ put_v(bc, par->video_delay);
avio_w8(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
- ff_put_v(bc, par->extradata_size);
+ put_v(bc, par->extradata_size);
avio_write(bc, par->extradata, par->extradata_size);
switch (par->codec_type) {
case AVMEDIA_TYPE_AUDIO:
- ff_put_v(bc, par->sample_rate);
- ff_put_v(bc, 1);
- ff_put_v(bc, par->channels);
+ put_v(bc, par->sample_rate);
+ put_v(bc, 1);
+ put_v(bc, par->channels);
break;
case AVMEDIA_TYPE_VIDEO:
- ff_put_v(bc, par->width);
- ff_put_v(bc, par->height);
+ put_v(bc, par->width);
+ put_v(bc, par->height);
if (st->sample_aspect_ratio.num <= 0 ||
st->sample_aspect_ratio.den <= 0) {
- ff_put_v(bc, 0);
- ff_put_v(bc, 0);
+ put_v(bc, 0);
+ put_v(bc, 0);
} else {
- ff_put_v(bc, st->sample_aspect_ratio.num);
- ff_put_v(bc, st->sample_aspect_ratio.den);
+ put_v(bc, st->sample_aspect_ratio.num);
+ put_v(bc, st->sample_aspect_ratio.den);
}
- ff_put_v(bc, 0); /* csp type -- unknown */
+ put_v(bc, 0); /* csp type -- unknown */
break;
default:
break;
while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)))
count += add_info(dyn_bc, t->key, t->value);
- ff_put_v(bc, 0); //stream_if_plus1
- ff_put_v(bc, 0); //chapter_id
- ff_put_v(bc, 0); //timestamp_start
- ff_put_v(bc, 0); //length
+ put_v(bc, 0); //stream_if_plus1
+ put_v(bc, 0); //chapter_id
+ put_v(bc, 0); //timestamp_start
+ put_v(bc, 0); //length
- ff_put_v(bc, count);
+ put_v(bc, count);
dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
avio_write(bc, dyn_buf, dyn_size);
dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
if (count) {
- ff_put_v(bc, stream_id + 1); //stream_id_plus1
- ff_put_v(bc, 0); //chapter_id
- ff_put_v(bc, 0); //timestamp_start
- ff_put_v(bc, 0); //length
+ 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
- ff_put_v(bc, count);
+ put_v(bc, count);
avio_write(bc, dyn_buf, dyn_size);
}
if (ret < 0)
return ret;
- ff_put_v(bc, 0); // stream_id_plus1
+ put_v(bc, 0); // stream_id_plus1
put_s(bc, id + 1); // chapter_id
put_tt(nut, nut->chapter[id].time_base, bc, ch->start); // chapter_start
- ff_put_v(bc, ch->end - ch->start); // chapter_len
+ put_v(bc, ch->end - ch->start); // chapter_len
while ((t = av_dict_get(ch->metadata, "", t, AV_DICT_IGNORE_SUFFIX)))
count += add_info(dyn_bc, t->key, t->value);
- ff_put_v(bc, count);
+ put_v(bc, count);
dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
avio_write(bc, dyn_buf, dyn_size);
put_tt(nut, nut->max_pts_tb, bc, nut->max_pts);
- ff_put_v(bc, nut->sp_count);
+ put_v(bc, nut->sp_count);
for (i=0; i<nut->sp_count; i++) {
av_tree_find(nut->syncpoints, &dummy, ff_nut_sp_pos_cmp, (void**)next_node);
- ff_put_v(bc, (next_node[1]->pos >> 4) - (dummy.pos>>4));
+ put_v(bc, (next_node[1]->pos >> 4) - (dummy.pos>>4));
dummy.pos = next_node[1]->pos;
}
for (; j<nut->sp_count && (nus->keyframe_pts[j] != AV_NOPTS_VALUE) == flag; j++)
n++;
- ff_put_v(bc, 1 + 2*flag + 4*n);
+ 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);
+ put_v(bc, nus->keyframe_pts[k] - last_pts);
last_pts = nus->keyframe_pts[k];
}
}
if (ret < 0)
return ret;
write_mainheader(nut, dyn_bc);
- put_packet(nut, bc, dyn_bc, 1, MAIN_STARTCODE);
+ put_packet(nut, bc, dyn_bc, MAIN_STARTCODE);
for (i = 0; i < nut->avf->nb_streams; i++) {
- ret = avio_open_dyn_buf(&dyn_bc);
- if (ret < 0)
- return ret;
ret = write_streamheader(avctx, dyn_bc, nut->avf->streams[i], i);
- if (ret < 0)
- return ret;
- put_packet(nut, bc, dyn_bc, 1, STREAM_STARTCODE);
+ if (ret < 0) {
+ goto fail;
+ }
+ put_packet(nut, bc, dyn_bc, STREAM_STARTCODE);
}
- ret = avio_open_dyn_buf(&dyn_bc);
- if (ret < 0)
- return ret;
write_globalinfo(nut, dyn_bc);
- put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE);
+ put_packet(nut, bc, dyn_bc, INFO_STARTCODE);
for (i = 0; i < nut->avf->nb_streams; i++) {
- ret = avio_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
- ffio_free_dyn_buf(&dyn_bc);
+ put_packet(nut, bc, dyn_bc, INFO_STARTCODE);
+ else if (ret < 0) {
+ goto fail;
+ }
}
for (i = 0; i < nut->avf->nb_chapters; i++) {
- ret = avio_open_dyn_buf(&dyn_bc);
- if (ret < 0)
- return ret;
ret = write_chapter(nut, dyn_bc, i);
if (ret < 0) {
- ffio_free_dyn_buf(&dyn_bc);
- return ret;
+ goto fail;
}
- put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE);
+ put_packet(nut, bc, dyn_bc, INFO_STARTCODE);
}
nut->last_syncpoint_pos = INT_MIN;
nut->header_count++;
- return 0;
+
+ ret = 0;
+fail:
+ ffio_free_dyn_buf(&dyn_bc);
+
+ return ret;
}
static int nut_write_header(AVFormatContext *s)
nut->chapter = av_calloc(s->nb_chapters, sizeof(*nut->chapter));
nut->time_base= av_calloc(s->nb_streams +
s->nb_chapters, sizeof(*nut->time_base));
- if (!nut->stream || !nut->chapter || !nut->time_base) {
- av_freep(&nut->stream);
- av_freep(&nut->chapter);
- av_freep(&nut->time_base);
+ if (!nut->stream || !nut->chapter || !nut->time_base)
return AVERROR(ENOMEM);
- }
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
if (s->avoid_negative_ts < 0)
s->avoid_negative_ts = 1;
- avio_flush(bc);
-
return 0;
}
flags |= FLAG_CHECKSUM;
if (FFABS(pkt->pts - nus->last_pts) > nus->max_pts_distance)
flags |= FLAG_CHECKSUM;
- if (pkt->size < nut->header_len[fc->header_idx] ||
- (pkt->size > 4096 && fc->header_idx) ||
- memcmp(pkt->data, nut->header[fc->header_idx],
- nut->header_len[fc->header_idx]))
- flags |= FLAG_HEADER_IDX;
+ if (fc->header_idx)
+ if (pkt->size < nut->header_len[fc->header_idx] ||
+ pkt->size > 4096 ||
+ memcmp(pkt->data, nut->header [fc->header_idx],
+ nut->header_len[fc->header_idx]))
+ flags |= FLAG_HEADER_IDX;
return flags | (fc->flags & FLAG_CODED);
}
}
put_s(dyn_bc, -2);
put_str(dyn_bc, "bin");
- ff_put_v(dyn_bc, pkt->side_data[i].size);
+ put_v(dyn_bc, pkt->side_data[i].size);
avio_write(dyn_bc, data, pkt->side_data[i].size);
sm_data_count++;
break;
put_str(dyn_bc, "ChannelLayout");
put_s(dyn_bc, -2);
put_str(dyn_bc, "u64");
- ff_put_v(bc, 8);
+ put_v(dyn_bc, 8);
avio_write(dyn_bc, data, 8); data+=8;
sm_data_count++;
}
}
fail:
- ff_put_v(bc, sm_data_count);
+ put_v(bc, sm_data_count);
dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
avio_write(bc, dyn_buf, dyn_size);
av_freep(&dyn_buf);
int index = av_index_search_timestamp(st, dts_tb,
AVSEEK_FLAG_BACKWARD);
if (index >= 0) {
- sp_pos = FFMIN(sp_pos, st->index_entries[index].pos);
- if (!nut->write_index && 2*index > st->nb_index_entries) {
- memmove(st->index_entries,
- st->index_entries + index,
- sizeof(*st->index_entries) * (st->nb_index_entries - index));
- st->nb_index_entries -= index;
+ sp_pos = FFMIN(sp_pos, st->internal->index_entries[index].pos);
+ if (!nut->write_index && 2*index > st->internal->nb_index_entries) {
+ memmove(st->internal->index_entries,
+ st->internal->index_entries + index,
+ sizeof(*st->internal->index_entries) * (st->internal->nb_index_entries - index));
+ st->internal->nb_index_entries -= index;
}
}
}
if (ret < 0)
goto fail;
put_tt(nut, nus->time_base, dyn_bc, pkt->dts);
- ff_put_v(dyn_bc, sp_pos != INT64_MAX ? (nut->last_syncpoint_pos - sp_pos) >> 4 : 0);
+ put_v(dyn_bc, sp_pos != INT64_MAX ? (nut->last_syncpoint_pos - sp_pos) >> 4 : 0);
if (nut->flags & NUT_BROADCAST) {
put_tt(nut, nus->time_base, dyn_bc,
av_rescale_q(av_gettime(), AV_TIME_BASE_Q, *nus->time_base));
}
- put_packet(nut, bc, dyn_bc, 1, SYNCPOINT_STARTCODE);
+ put_packet(nut, bc, dyn_bc, SYNCPOINT_STARTCODE);
+ ffio_free_dyn_buf(&dyn_bc);
if (nut->write_index) {
if ((ret = ff_nut_add_sp(nut, nut->last_syncpoint_pos, 0 /*unused*/, pkt->dts)) < 0)
continue;
if (flags & FLAG_STREAM_ID)
- length += ff_get_v_length(pkt->stream_index);
+ length += get_v_length(pkt->stream_index);
if (data_size % fc->size_mul != fc->size_lsb)
continue;
if (flags & FLAG_SIZE_MSB)
- length += ff_get_v_length(data_size / fc->size_mul);
+ length += get_v_length(data_size / fc->size_mul);
if (flags & FLAG_CHECKSUM)
length += 4;
if (flags & FLAG_CODED_PTS)
- length += ff_get_v_length(coded_pts);
+ length += get_v_length(coded_pts);
if ( (flags & FLAG_CODED)
&& nut->header_len[best_header_idx] > nut->header_len[fc->header_idx] + 1) {
ffio_init_checksum(bc, ff_crc04C11DB7_update, 0);
avio_w8(bc, frame_code);
if (flags & FLAG_CODED) {
- ff_put_v(bc, (flags ^ needed_flags) & ~(FLAG_CODED));
+ put_v(bc, (flags ^ needed_flags) & ~(FLAG_CODED));
flags = needed_flags;
}
- if (flags & FLAG_STREAM_ID) ff_put_v(bc, pkt->stream_index);
- if (flags & FLAG_CODED_PTS) ff_put_v(bc, coded_pts);
- if (flags & FLAG_SIZE_MSB ) ff_put_v(bc, data_size / fc->size_mul);
- if (flags & FLAG_HEADER_IDX) ff_put_v(bc, header_idx = best_header_idx);
+ if (flags & FLAG_STREAM_ID) put_v(bc, pkt->stream_index);
+ if (flags & FLAG_CODED_PTS) put_v(bc, coded_pts);
+ if (flags & FLAG_SIZE_MSB ) put_v(bc, data_size / fc->size_mul);
+ if (flags & FLAG_HEADER_IDX) put_v(bc, header_idx = best_header_idx);
if (flags & FLAG_CHECKSUM) avio_wl32(bc, ffio_get_checksum(bc));
else ffio_get_checksum(bc);
while (nut->header_count < 3)
write_headers(s, bc);
+ if (!nut->sp_count)
+ return 0;
+
ret = avio_open_dyn_buf(&dyn_bc);
- if (ret >= 0 && nut->sp_count) {
- av_assert1(nut->write_index);
+ if (ret >= 0) {
+ av_assert1(nut->write_index); // sp_count should be 0 if no index is going to be written
write_index(nut, dyn_bc);
- put_packet(nut, bc, dyn_bc, 1, INDEX_STARTCODE);
+ put_packet(nut, bc, dyn_bc, INDEX_STARTCODE);
+ ffio_free_dyn_buf(&dyn_bc);
}
return 0;