-#ifdef CONFIG_MUXERS
-
-static void put_v(ByteIOContext *bc, uint64_t val)
-{
- int i;
-
-//av_log(NULL, AV_LOG_DEBUG, "put_v()= %lld\n", val);
- val &= 0x7FFFFFFFFFFFFFFFULL; // FIXME can only encode upto 63 bits currently
- i= get_length(val);
-
- for (i-=7; i>0; i-=7){
- put_byte(bc, 0x80 | (val>>i));
- }
-
- put_byte(bc, val&0x7f);
-}
-
-/**
- * stores a string as vb.
- */
-static void put_str(ByteIOContext *bc, const char *string){
- int len= strlen(string);
-
- put_v(bc, len);
- put_buffer(bc, string, len);
-}
-
-static void put_s(ByteIOContext *bc, int64_t val){
- if (val<=0) put_v(bc, -2*val );
- else put_v(bc, 2*val-1);
-}
-
-static void put_vb(ByteIOContext *bc, uint64_t val){
- int i;
-
- for (i=8; val>>i; i+=8);
-
- put_v(bc, i>>3);
- for(i-=8; i>=0; i-=8)
- put_byte(bc, (val>>i)&0xFF);
-}
-
-#ifdef TRACE
-static inline void put_v_trace(ByteIOContext *bc, uint64_t v, char *file, char *func, int line){
- printf("get_v %5lld / %llX in %s %s:%d\n", v, v, file, func, line);
-
- put_v(bc, v);
-}
-
-static inline void put_s_trace(ByteIOContext *bc, int64_t v, char *file, char *func, int line){
- printf("get_s %5lld / %llX in %s %s:%d\n", v, v, file, func, line);
-
- put_s(bc, v);
-}
-
-static inline void put_vb_trace(ByteIOContext *bc, uint64_t v, char *file, char *func, int line){
- printf("get_vb %5lld / %llX in %s %s:%d\n", v, v, file, func, line);
-
- put_vb(bc, v);
-}
-#define put_v(bc, v) put_v_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#define put_s(bc, v) put_s_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#define put_vb(bc, v) put_vb_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#endif
-
-static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size, int calculate_checksum)
-{
- put_flush_packet(bc);
- nut->packet_start[2]= url_ftell(bc) - 8;
- nut->written_packet_size = max_size;
-
- /* packet header */
- put_v(bc, nut->written_packet_size); /* forward ptr */
-
- if(calculate_checksum)
- init_checksum(bc, update_adler32, 0);
-
- return 0;
-}
-
-/**
- *
- * must not be called more then once per packet
- */
-static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size, int calculate_checksum){
- int64_t start= nut->packet_start[2];
- int64_t cur= url_ftell(bc);
- int size= cur - start - get_length(nut->written_packet_size)/7 - 8;
-
- if(calculate_checksum)
- size += 4;
-
- if(size != nut->written_packet_size){
- int i;
-
- assert( size <= nut->written_packet_size );
-
- url_fseek(bc, start + 8, SEEK_SET);
- for(i=get_length(size); i < get_length(nut->written_packet_size); i+=7)
- put_byte(bc, 0x80);
- put_v(bc, size);
-
- url_fseek(bc, cur, SEEK_SET);
- nut->written_packet_size= size; //FIXME may fail if multiple updates with differing sizes, as get_length may differ
-
- if(calculate_checksum)
- put_be32(bc, get_checksum(bc));
- }
-
- return 0;
-}
-
-static int nut_write_header(AVFormatContext *s)
-{
- NUTContext *nut = s->priv_data;
- ByteIOContext *bc = &s->pb;
- AVCodecContext *codec;
- int i, j, tmp_time, tmp_flags,tmp_stream, tmp_mul, tmp_size, tmp_fields;
-
- if (strcmp(s->filename, "./data/b-libav.nut")) {
- av_log(s, AV_LOG_ERROR, " libavformat NUT is non-compliant and disabled\n");
- return -1;
- }
-
- nut->avf= s;
-
- nut->stream =
- av_mallocz(sizeof(StreamContext)*s->nb_streams);
-
-
- put_buffer(bc, ID_STRING, strlen(ID_STRING));
- put_byte(bc, 0);
- nut->packet_start[2]= url_ftell(bc);
-
- /* main header */
- put_be64(bc, MAIN_STARTCODE);
- put_packetheader(nut, bc, 120+5*256, 1);
- put_v(bc, 2); /* version */
- put_v(bc, s->nb_streams);
- put_v(bc, MAX_DISTANCE);
- put_v(bc, MAX_SHORT_DISTANCE);
-
- put_v(bc, nut->rate_num=1);
- put_v(bc, nut->rate_den=2);
- put_v(bc, nut->short_startcode=0x4EFE79);
-
- build_frame_code(s);
- assert(nut->frame_code['N'].flags == FLAG_INVALID);
-
- tmp_time= tmp_flags= tmp_stream= tmp_mul= tmp_size= /*tmp_res=*/ INT_MAX;
- for(i=0; i<256;){
- tmp_fields=0;
- tmp_size= 0;
- if(tmp_time != nut->frame_code[i].timestamp_delta) tmp_fields=1;
- if(tmp_mul != nut->frame_code[i].size_mul ) tmp_fields=2;
- if(tmp_stream != nut->frame_code[i].stream_id_plus1) tmp_fields=3;
- if(tmp_size != nut->frame_code[i].size_lsb ) tmp_fields=4;
-// if(tmp_res != nut->frame_code[i].res ) tmp_fields=5;
-
- tmp_time = nut->frame_code[i].timestamp_delta;
- tmp_flags = nut->frame_code[i].flags;
- tmp_stream= nut->frame_code[i].stream_id_plus1;
- tmp_mul = nut->frame_code[i].size_mul;
- tmp_size = nut->frame_code[i].size_lsb;
-// tmp_res = nut->frame_code[i].res;
-
- for(j=0; i<256; j++,i++){
- if(nut->frame_code[i].timestamp_delta != tmp_time ) break;
- if(nut->frame_code[i].flags != tmp_flags ) break;
- if(nut->frame_code[i].stream_id_plus1 != tmp_stream) break;
- if(nut->frame_code[i].size_mul != tmp_mul ) break;
- if(nut->frame_code[i].size_lsb != tmp_size+j) break;
-// if(nut->frame_code[i].res != tmp_res ) break;
- }
- if(j != tmp_mul - tmp_size) tmp_fields=6;
-
- put_v(bc, tmp_flags);
- put_v(bc, tmp_fields);
- if(tmp_fields>0) put_s(bc, tmp_time);
- 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);
- }
-
- update_packetheader(nut, bc, 0, 1);
-
- /* stream headers */
- for (i = 0; i < s->nb_streams; i++)
- {
- int nom, denom, ssize;
-
- codec = s->streams[i]->codec;
-
- put_be64(bc, STREAM_STARTCODE);
- put_packetheader(nut, bc, 120 + codec->extradata_size, 1);
- put_v(bc, i /*s->streams[i]->index*/);
- switch(codec->codec_type){
- case CODEC_TYPE_VIDEO: put_v(bc, 0); break;
- case CODEC_TYPE_AUDIO: put_v(bc, 1); break;
-// case CODEC_TYPE_TEXT : put_v(bc, 2); break;
- case CODEC_TYPE_DATA : put_v(bc, 3); break;
- default: return -1;
- }
- if (codec->codec_tag)
- put_vb(bc, codec->codec_tag);
- else if (codec->codec_type == CODEC_TYPE_VIDEO)
- {
- put_vb(bc, codec_get_bmp_tag(codec->codec_id));
- }
- else if (codec->codec_type == CODEC_TYPE_AUDIO)
- {
- put_vb(bc, codec_get_wav_tag(codec->codec_id));
- }
- else
- put_vb(bc, 0);
-
- ff_parse_specific_params(codec, &nom, &ssize, &denom);
-
- nut->stream[i].rate_num= nom;
- nut->stream[i].rate_den= denom;
- av_set_pts_info(s->streams[i], 60, denom, nom);
-
- put_v(bc, codec->bit_rate);
- put_vb(bc, 0); /* no language code */
- put_v(bc, nom);
- put_v(bc, denom);
- if(nom / denom < 1000)
- nut->stream[i].msb_timestamp_shift = 7;
- else
- nut->stream[i].msb_timestamp_shift = 14;
- put_v(bc, nut->stream[i].msb_timestamp_shift);
- put_v(bc, codec->has_b_frames);
- put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
-
- if(codec->extradata_size){
- put_v(bc, 1);
- put_v(bc, codec->extradata_size);
- put_buffer(bc, codec->extradata, codec->extradata_size);
- }
- put_v(bc, 0); /* end of codec specific headers */
-
- switch(codec->codec_type)
- {
- case CODEC_TYPE_AUDIO:
- put_v(bc, codec->sample_rate);
- put_v(bc, 1);
- put_v(bc, codec->channels);
- break;
- case CODEC_TYPE_VIDEO:
- put_v(bc, codec->width);
- put_v(bc, codec->height);
- put_v(bc, codec->sample_aspect_ratio.num);
- put_v(bc, codec->sample_aspect_ratio.den);
- put_v(bc, 0); /* csp type -- unknown */
- break;
- default:
- break;
- }
- update_packetheader(nut, bc, 0, 1);
- }
-
- /* info header */
- put_be64(bc, INFO_STARTCODE);
- put_packetheader(nut, bc, 30+strlen(s->author)+strlen(s->title)+
- strlen(s->comment)+strlen(s->copyright)+strlen(LIBAVFORMAT_IDENT), 1);
- if (s->author[0])
- {
- put_v(bc, 9); /* type */
- put_str(bc, s->author);
- }
- if (s->title[0])
- {
- put_v(bc, 10); /* type */
- put_str(bc, s->title);
- }
- if (s->comment[0])
- {
- put_v(bc, 11); /* type */
- put_str(bc, s->comment);
- }
- if (s->copyright[0])
- {
- put_v(bc, 12); /* type */
- put_str(bc, s->copyright);
- }
- /* encoder */
- if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)){
- put_v(bc, 13); /* type */
- put_str(bc, LIBAVFORMAT_IDENT);
- }
-
- put_v(bc, 0); /* eof info */
- update_packetheader(nut, bc, 0, 1);
-
- put_flush_packet(bc);
-
- return 0;
-}
-
-static int nut_write_packet(AVFormatContext *s, AVPacket *pkt)
-{
- NUTContext *nut = s->priv_data;
- StreamContext *stream= &nut->stream[pkt->stream_index];
- ByteIOContext *bc = &s->pb;
- int key_frame = 0, full_pts=0;
- AVCodecContext *enc;
- int64_t coded_pts;
- int frame_type, best_length, frame_code, flags, i, size_mul, size_lsb, time_delta;
- const int64_t frame_start= url_ftell(bc);
- int64_t pts= pkt->pts;
- int size= pkt->size;
- int stream_index= pkt->stream_index;
-
- enc = s->streams[stream_index]->codec;
- key_frame = !!(pkt->flags & PKT_FLAG_KEY);
-
- frame_type=0;
- if(frame_start + size + 20 - FFMAX(nut->packet_start[1], nut->packet_start[2]) > MAX_DISTANCE)
- frame_type=2;
- if(key_frame && !stream->last_key_frame)
- frame_type=2;
-
- if(frame_type>1){
- int64_t global_ts= av_rescale(pts, stream->rate_den*(int64_t)nut->rate_num, stream->rate_num*(int64_t)nut->rate_den);
- reset(s, global_ts);
- put_be64(bc, KEYFRAME_STARTCODE);
- put_v(bc, global_ts);
- }
- assert(stream->last_pts != AV_NOPTS_VALUE);
- coded_pts = pts & ((1<<stream->msb_timestamp_shift)-1);
- if(lsb2full(stream, coded_pts) != pts)
- full_pts=1;
-
- if(full_pts)
- coded_pts= pts + (1<<stream->msb_timestamp_shift);
-
- best_length=INT_MAX;
- frame_code= -1;
- for(i=0; i<256; i++){
- int stream_id_plus1= nut->frame_code[i].stream_id_plus1;
- int fc_key_frame;
- int length=0;
- size_mul= nut->frame_code[i].size_mul;
- size_lsb= nut->frame_code[i].size_lsb;
- time_delta= nut->frame_code[i].timestamp_delta;
- flags= nut->frame_code[i].flags;
-
- assert(size_mul > size_lsb);
-
- if(stream_id_plus1 == 0) length+= get_length(stream_index);
- else if(stream_id_plus1 - 1 != stream_index)
- continue;
- fc_key_frame= !!(flags & FLAG_KEY_FRAME);
-
- assert(key_frame==0 || key_frame==1);
- if(fc_key_frame != key_frame)
- continue;
-
- if(flags & FLAG_DATA_SIZE){
- if(size % size_mul != size_lsb)
- continue;
- length += get_length(size / size_mul);
- }else if(size != size_lsb)
- continue;
-
- if(full_pts && time_delta)
- continue;
-
- if(!time_delta){
- length += get_length(coded_pts);
- }else{
- if(time_delta != pts - stream->last_pts)
- continue;
- }
-
- if(length < best_length){
- best_length= length;
- frame_code=i;
- }
-// av_log(s, AV_LOG_DEBUG, "%d %d %d %d %d %d %d %d %d %d\n", key_frame, frame_type, full_pts, size, stream_index, flags, size_mul, size_lsb, stream_id_plus1, length);
- }
-
- assert(frame_code != -1);
- flags= nut->frame_code[frame_code].flags;
- size_mul= nut->frame_code[frame_code].size_mul;
- size_lsb= nut->frame_code[frame_code].size_lsb;
- time_delta= nut->frame_code[frame_code].timestamp_delta;
-#ifdef TRACE
- best_length /= 7;
- best_length ++; //frame_code
- if(frame_type==2){
- best_length += 8; // startcode
- }
- av_log(s, AV_LOG_DEBUG, "kf:%d ft:%d pt:%d fc:%2X len:%2d size:%d stream:%d flag:%d mul:%d lsb:%d s+1:%d pts_delta:%d pts:%lld fs:%lld\n", key_frame, frame_type, full_pts ? 1 : 0, frame_code, best_length, size, stream_index, flags, size_mul, size_lsb, nut->frame_code[frame_code].stream_id_plus1,(int)(pts - stream->last_pts), pts, frame_start);
-// av_log(s, AV_LOG_DEBUG, "%d %d %d\n", stream->lru_pts_delta[0], stream->lru_pts_delta[1], stream->lru_pts_delta[2]);
-#endif
-
- assert(frame_type != 1); //short startcode not implemented yet
- put_byte(bc, frame_code);
-
- if(nut->frame_code[frame_code].stream_id_plus1 == 0)
- put_v(bc, stream_index);
- if (!time_delta){
- put_v(bc, coded_pts);
- }
- if(flags & FLAG_DATA_SIZE)
- put_v(bc, size / size_mul);
- else
- assert(size == size_lsb);
- if(size > MAX_DISTANCE){
- assert(frame_type > 1);
- }
-
- put_buffer(bc, pkt->data, size);
-
- update(nut, stream_index, frame_start, frame_type, frame_code, key_frame, size, pts);
-
- return 0;