+#include "internal.h"
+#include "avio_internal.h"
+
+static int find_expected_header(AVCodecContext *c, int size, int key_frame, uint8_t out[64]){
+ int sample_rate= c->sample_rate;
+
+ if(size>4096)
+ return 0;
+
+ AV_WB24(out, 1);
+
+ if(c->codec_id == 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){
+ return 3;
+ }else if(c->codec_id == CODEC_ID_H264){
+ return 3;
+ }else if(c->codec_id == CODEC_ID_MP3 || c->codec_id == CODEC_ID_MP2){
+ int lsf, mpeg25, sample_rate_index, bitrate_index, frame_size;
+ int layer= c->codec_id == CODEC_ID_MP3 ? 3 : 2;
+ unsigned int header= 0xFFF00000;
+
+ lsf = sample_rate < (24000+32000)/2;
+ mpeg25 = sample_rate < (12000+16000)/2;
+ sample_rate <<= lsf + mpeg25;
+ if (sample_rate < (32000 + 44100)/2) sample_rate_index=2;
+ else if(sample_rate < (44100 + 48000)/2) sample_rate_index=0;
+ else sample_rate_index=1;
+
+ sample_rate= avpriv_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25);
+
+ for(bitrate_index=2; bitrate_index<30; bitrate_index++){
+ frame_size = avpriv_mpa_bitrate_tab[lsf][layer-1][bitrate_index>>1];
+ frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index&1);
+
+ if(frame_size == size)
+ break;
+ }
+
+ header |= (!lsf)<<19;
+ header |= (4-layer)<<17;
+ header |= 1<<16; //no crc
+ AV_WB32(out, header);
+ if(size <= 0)
+ return 2; //we guess there is no crc, if there is one the user clearly does not care about overhead
+ if(bitrate_index == 30)
+ return -1; //something is wrong ...
+
+ header |= (bitrate_index>>1)<<12;
+ header |= sample_rate_index<<10;
+ header |= (bitrate_index&1)<<9;
+
+ return 2; //FIXME actually put the needed ones in build_elision_headers()
+ return 3; //we guess that the private bit is not set
+//FIXME the above assumptions should be checked, if these turn out false too often something should be done
+ }
+ return 0;
+}
+
+static int find_header_idx(AVFormatContext *s, AVCodecContext *c, int size, int frame_type){
+ NUTContext *nut = s->priv_data;
+ uint8_t out[64];
+ int i;
+ int len= find_expected_header(c, size, frame_type, out);
+
+//av_log(NULL, AV_LOG_ERROR, "expected_h len=%d size=%d codec_id=%d\n", len, size, c->codec_id);
+
+ for(i=1; i<nut->header_count; i++){
+ if( len == nut->header_len[i]
+ && !memcmp(out, nut->header[i], len)){
+// av_log(NULL, AV_LOG_ERROR, "found %d\n", i);
+ return i;
+ }
+ }
+// av_log(NULL, AV_LOG_ERROR, "nothing found\n");
+ return 0;
+}
+
+static void build_elision_headers(AVFormatContext *s){
+ NUTContext *nut = s->priv_data;
+ int i;
+ //FIXME this is lame
+ //FIXME write a 2pass mode to find the maximal headers
+ static const uint8_t headers[][5]={
+ {3, 0x00, 0x00, 0x01},
+ {4, 0x00, 0x00, 0x01, 0xB6},
+ {2, 0xFF, 0xFA}, //mp3+crc
+ {2, 0xFF, 0xFB}, //mp3
+ {2, 0xFF, 0xFC}, //mp2+crc
+ {2, 0xFF, 0xFD}, //mp2
+ };
+
+ nut->header_count= 7;
+ for(i=1; i<nut->header_count; i++){
+ nut->header_len[i]= headers[i-1][0];
+ nut->header [i]= &headers[i-1][1];
+ }
+}