00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "avformat.h"
00022 #include "avio_internal.h"
00023 #include "rm.h"
00024
00025 typedef struct {
00026 int nb_packets;
00027 int packet_total_size;
00028 int packet_max_size;
00029
00030 int bit_rate;
00031 float frame_rate;
00032 int nb_frames;
00033 int total_frames;
00034 int num;
00035 AVCodecContext *enc;
00036 } StreamInfo;
00037
00038 typedef struct {
00039 StreamInfo streams[2];
00040 StreamInfo *audio_stream, *video_stream;
00041 int data_pos;
00042 } RMMuxContext;
00043
00044
00045 #define BUFFER_DURATION 0
00046
00047
00048 static void put_str(AVIOContext *s, const char *tag)
00049 {
00050 avio_wb16(s,strlen(tag));
00051 while (*tag) {
00052 avio_w8(s, *tag++);
00053 }
00054 }
00055
00056 static void put_str8(AVIOContext *s, const char *tag)
00057 {
00058 avio_w8(s, strlen(tag));
00059 while (*tag) {
00060 avio_w8(s, *tag++);
00061 }
00062 }
00063
00064 static int rv10_write_header(AVFormatContext *ctx,
00065 int data_size, int index_pos)
00066 {
00067 RMMuxContext *rm = ctx->priv_data;
00068 AVIOContext *s = ctx->pb;
00069 StreamInfo *stream;
00070 unsigned char *data_offset_ptr, *start_ptr;
00071 const char *desc, *mimetype;
00072 int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i;
00073 int bit_rate, v, duration, flags, data_pos;
00074 AVMetadataTag *tag;
00075
00076 start_ptr = s->buf_ptr;
00077
00078 ffio_wfourcc(s, ".RMF");
00079 avio_wb32(s,18);
00080 avio_wb16(s,0);
00081 avio_wb32(s,0);
00082 avio_wb32(s,4 + ctx->nb_streams);
00083
00084 ffio_wfourcc(s,"PROP");
00085 avio_wb32(s, 50);
00086 avio_wb16(s, 0);
00087 packet_max_size = 0;
00088 packet_total_size = 0;
00089 nb_packets = 0;
00090 bit_rate = 0;
00091 duration = 0;
00092 for(i=0;i<ctx->nb_streams;i++) {
00093 StreamInfo *stream = &rm->streams[i];
00094 bit_rate += stream->bit_rate;
00095 if (stream->packet_max_size > packet_max_size)
00096 packet_max_size = stream->packet_max_size;
00097 nb_packets += stream->nb_packets;
00098 packet_total_size += stream->packet_total_size;
00099
00100 v = (int) (1000.0 * (float)stream->total_frames / stream->frame_rate);
00101 if (v > duration)
00102 duration = v;
00103 }
00104 avio_wb32(s, bit_rate);
00105 avio_wb32(s, bit_rate);
00106 avio_wb32(s, packet_max_size);
00107 if (nb_packets > 0)
00108 packet_avg_size = packet_total_size / nb_packets;
00109 else
00110 packet_avg_size = 0;
00111 avio_wb32(s, packet_avg_size);
00112 avio_wb32(s, nb_packets);
00113 avio_wb32(s, duration);
00114 avio_wb32(s, BUFFER_DURATION);
00115 avio_wb32(s, index_pos);
00116
00117 data_offset_ptr = s->buf_ptr;
00118 avio_wb32(s, 0);
00119 avio_wb16(s, ctx->nb_streams);
00120 flags = 1 | 2;
00121 if (url_is_streamed(s))
00122 flags |= 4;
00123 avio_wb16(s, flags);
00124
00125
00126
00127 ffio_wfourcc(s,"CONT");
00128 size = 4 * 2 + 10;
00129 for(i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) {
00130 tag = av_metadata_get(ctx->metadata, ff_rm_metadata[i], NULL, 0);
00131 if(tag) size += strlen(tag->value);
00132 }
00133 avio_wb32(s,size);
00134 avio_wb16(s,0);
00135 for(i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) {
00136 tag = av_metadata_get(ctx->metadata, ff_rm_metadata[i], NULL, 0);
00137 put_str(s, tag ? tag->value : "");
00138 }
00139
00140 for(i=0;i<ctx->nb_streams;i++) {
00141 int codec_data_size;
00142
00143 stream = &rm->streams[i];
00144
00145 if (stream->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
00146 desc = "The Audio Stream";
00147 mimetype = "audio/x-pn-realaudio";
00148 codec_data_size = 73;
00149 } else {
00150 desc = "The Video Stream";
00151 mimetype = "video/x-pn-realvideo";
00152 codec_data_size = 34;
00153 }
00154
00155 ffio_wfourcc(s,"MDPR");
00156 size = 10 + 9 * 4 + strlen(desc) + strlen(mimetype) + codec_data_size;
00157 avio_wb32(s, size);
00158 avio_wb16(s, 0);
00159
00160 avio_wb16(s, i);
00161 avio_wb32(s, stream->bit_rate);
00162 avio_wb32(s, stream->bit_rate);
00163 avio_wb32(s, stream->packet_max_size);
00164 if (stream->nb_packets > 0)
00165 packet_avg_size = stream->packet_total_size /
00166 stream->nb_packets;
00167 else
00168 packet_avg_size = 0;
00169 avio_wb32(s, packet_avg_size);
00170 avio_wb32(s, 0);
00171 avio_wb32(s, BUFFER_DURATION);
00172
00173 if (url_is_streamed(s) || !stream->total_frames)
00174 avio_wb32(s, (int)(3600 * 1000));
00175 else
00176 avio_wb32(s, (int)(stream->total_frames * 1000 / stream->frame_rate));
00177 put_str8(s, desc);
00178 put_str8(s, mimetype);
00179 avio_wb32(s, codec_data_size);
00180
00181 if (stream->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
00182 int coded_frame_size, fscode, sample_rate;
00183 sample_rate = stream->enc->sample_rate;
00184 coded_frame_size = (stream->enc->bit_rate *
00185 stream->enc->frame_size) / (8 * sample_rate);
00186
00187 avio_write(s, ".ra", 3);
00188 avio_w8(s, 0xfd);
00189 avio_wb32(s, 0x00040000);
00190 ffio_wfourcc(s, ".ra4");
00191 avio_wb32(s, 0x01b53530);
00192 avio_wb16(s, 4);
00193 avio_wb32(s, 0x39);
00194
00195 switch(sample_rate) {
00196 case 48000:
00197 case 24000:
00198 case 12000:
00199 fscode = 1;
00200 break;
00201 default:
00202 case 44100:
00203 case 22050:
00204 case 11025:
00205 fscode = 2;
00206 break;
00207 case 32000:
00208 case 16000:
00209 case 8000:
00210 fscode = 3;
00211 }
00212 avio_wb16(s, fscode);
00213
00214
00215 if (coded_frame_size == 557)
00216 coded_frame_size--;
00217 avio_wb32(s, coded_frame_size);
00218 avio_wb32(s, 0x51540);
00219 avio_wb32(s, 0x249f0);
00220 avio_wb32(s, 0x249f0);
00221 avio_wb16(s, 0x01);
00222
00223 avio_wb16(s, coded_frame_size);
00224 avio_wb32(s, 0);
00225 avio_wb16(s, stream->enc->sample_rate);
00226 avio_wb32(s, 0x10);
00227 avio_wb16(s, stream->enc->channels);
00228 put_str8(s, "Int0");
00229 if (stream->enc->codec_tag) {
00230 avio_w8(s, 4);
00231 avio_wl32(s, stream->enc->codec_tag);
00232 } else {
00233 av_log(ctx, AV_LOG_ERROR, "Invalid codec tag\n");
00234 return -1;
00235 }
00236 avio_wb16(s, 0);
00237 avio_wb16(s, 0);
00238 avio_wb16(s, 0);
00239 avio_w8(s, 0);
00240 } else {
00241
00242 avio_wb32(s,34);
00243 ffio_wfourcc(s, "VIDO");
00244 if(stream->enc->codec_id == CODEC_ID_RV10)
00245 ffio_wfourcc(s,"RV10");
00246 else
00247 ffio_wfourcc(s,"RV20");
00248 avio_wb16(s, stream->enc->width);
00249 avio_wb16(s, stream->enc->height);
00250 avio_wb16(s, (int) stream->frame_rate);
00251 avio_wb32(s,0);
00252 avio_wb16(s, (int) stream->frame_rate);
00253 avio_wb32(s,0);
00254 avio_wb16(s, 8);
00255
00256
00257
00258 if(stream->enc->codec_id == CODEC_ID_RV10)
00259 avio_wb32(s,0x10000000);
00260 else
00261 avio_wb32(s,0x20103001);
00262
00263 }
00264 }
00265
00266
00267 data_pos = s->buf_ptr - start_ptr;
00268 rm->data_pos = data_pos;
00269 data_offset_ptr[0] = data_pos >> 24;
00270 data_offset_ptr[1] = data_pos >> 16;
00271 data_offset_ptr[2] = data_pos >> 8;
00272 data_offset_ptr[3] = data_pos;
00273
00274
00275 ffio_wfourcc(s, "DATA");
00276 avio_wb32(s,data_size + 10 + 8);
00277 avio_wb16(s,0);
00278
00279 avio_wb32(s, nb_packets);
00280 avio_wb32(s,0);
00281 return 0;
00282 }
00283
00284 static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream,
00285 int length, int key_frame)
00286 {
00287 int timestamp;
00288 AVIOContext *s = ctx->pb;
00289
00290 stream->nb_packets++;
00291 stream->packet_total_size += length;
00292 if (length > stream->packet_max_size)
00293 stream->packet_max_size = length;
00294
00295 avio_wb16(s,0);
00296 avio_wb16(s,length + 12);
00297 avio_wb16(s, stream->num);
00298 timestamp = (1000 * (float)stream->nb_frames) / stream->frame_rate;
00299 avio_wb32(s, timestamp);
00300 avio_w8(s, 0);
00301 avio_w8(s, key_frame ? 2 : 0);
00302 }
00303
00304 static int rm_write_header(AVFormatContext *s)
00305 {
00306 RMMuxContext *rm = s->priv_data;
00307 StreamInfo *stream;
00308 int n;
00309 AVCodecContext *codec;
00310
00311 for(n=0;n<s->nb_streams;n++) {
00312 s->streams[n]->id = n;
00313 codec = s->streams[n]->codec;
00314 stream = &rm->streams[n];
00315 memset(stream, 0, sizeof(StreamInfo));
00316 stream->num = n;
00317 stream->bit_rate = codec->bit_rate;
00318 stream->enc = codec;
00319
00320 switch(codec->codec_type) {
00321 case AVMEDIA_TYPE_AUDIO:
00322 rm->audio_stream = stream;
00323 stream->frame_rate = (float)codec->sample_rate / (float)codec->frame_size;
00324
00325 stream->packet_max_size = 1024;
00326 stream->nb_packets = 0;
00327 stream->total_frames = stream->nb_packets;
00328 break;
00329 case AVMEDIA_TYPE_VIDEO:
00330 rm->video_stream = stream;
00331 stream->frame_rate = (float)codec->time_base.den / (float)codec->time_base.num;
00332
00333 stream->packet_max_size = 4096;
00334 stream->nb_packets = 0;
00335 stream->total_frames = stream->nb_packets;
00336 break;
00337 default:
00338 return -1;
00339 }
00340 }
00341
00342 if (rv10_write_header(s, 0, 0))
00343 return AVERROR_INVALIDDATA;
00344 put_flush_packet(s->pb);
00345 return 0;
00346 }
00347
00348 static int rm_write_audio(AVFormatContext *s, const uint8_t *buf, int size, int flags)
00349 {
00350 uint8_t *buf1;
00351 RMMuxContext *rm = s->priv_data;
00352 AVIOContext *pb = s->pb;
00353 StreamInfo *stream = rm->audio_stream;
00354 int i;
00355
00356
00357 buf1= (uint8_t*) av_malloc( size * sizeof(uint8_t) );
00358
00359 write_packet_header(s, stream, size, !!(flags & AV_PKT_FLAG_KEY));
00360
00361 if (stream->enc->codec_id == CODEC_ID_AC3) {
00362
00363 for(i=0;i<size;i+=2) {
00364 buf1[i] = buf[i+1];
00365 buf1[i+1] = buf[i];
00366 }
00367 avio_write(pb, buf1, size);
00368 } else {
00369 avio_write(pb, buf, size);
00370 }
00371 put_flush_packet(pb);
00372 stream->nb_frames++;
00373 av_free(buf1);
00374 return 0;
00375 }
00376
00377 static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int flags)
00378 {
00379 RMMuxContext *rm = s->priv_data;
00380 AVIOContext *pb = s->pb;
00381 StreamInfo *stream = rm->video_stream;
00382 int key_frame = !!(flags & AV_PKT_FLAG_KEY);
00383
00384
00385
00386
00387
00388 #if 1
00389 write_packet_header(s, stream, size + 7 + (size >= 0x4000)*4, key_frame);
00390
00391 avio_w8(pb, 0x81);
00392
00393
00394 if (key_frame) {
00395 avio_w8(pb, 0x81);
00396 } else {
00397 avio_w8(pb, 0x01);
00398 }
00399 if(size >= 0x4000){
00400 avio_wb32(pb, size);
00401 avio_wb32(pb, size);
00402 }else{
00403 avio_wb16(pb, 0x4000 | size);
00404 avio_wb16(pb, 0x4000 | size);
00405 }
00406 #else
00407
00408 write_packet_header(s, size + 6);
00409 avio_w8(pb, 0xc0);
00410 avio_wb16(pb, 0x4000 + size);
00411 avio_wb16(pb, 0x4000 + packet_number * 126);
00412 #endif
00413 avio_w8(pb, stream->nb_frames & 0xff);
00414
00415 avio_write(pb, buf, size);
00416 put_flush_packet(pb);
00417
00418 stream->nb_frames++;
00419 return 0;
00420 }
00421
00422 static int rm_write_packet(AVFormatContext *s, AVPacket *pkt)
00423 {
00424 if (s->streams[pkt->stream_index]->codec->codec_type ==
00425 AVMEDIA_TYPE_AUDIO)
00426 return rm_write_audio(s, pkt->data, pkt->size, pkt->flags);
00427 else
00428 return rm_write_video(s, pkt->data, pkt->size, pkt->flags);
00429 }
00430
00431 static int rm_write_trailer(AVFormatContext *s)
00432 {
00433 RMMuxContext *rm = s->priv_data;
00434 int data_size, index_pos, i;
00435 AVIOContext *pb = s->pb;
00436
00437 if (!url_is_streamed(s->pb)) {
00438
00439 index_pos = avio_seek(pb, 0, SEEK_CUR);
00440 data_size = index_pos - rm->data_pos;
00441
00442
00443
00444
00445 avio_wb32(pb, 0);
00446 avio_wb32(pb, 0);
00447
00448 avio_seek(pb, 0, SEEK_SET);
00449 for(i=0;i<s->nb_streams;i++)
00450 rm->streams[i].total_frames = rm->streams[i].nb_frames;
00451 rv10_write_header(s, data_size, 0);
00452 } else {
00453
00454 avio_wb32(pb, 0);
00455 avio_wb32(pb, 0);
00456 }
00457 put_flush_packet(pb);
00458 return 0;
00459 }
00460
00461
00462 AVOutputFormat ff_rm_muxer = {
00463 "rm",
00464 NULL_IF_CONFIG_SMALL("RealMedia format"),
00465 "application/vnd.rn-realmedia",
00466 "rm,ra",
00467 sizeof(RMMuxContext),
00468 CODEC_ID_AC3,
00469 CODEC_ID_RV10,
00470 rm_write_header,
00471 rm_write_packet,
00472 rm_write_trailer,
00473 .codec_tag= (const AVCodecTag* const []){ff_rm_codec_tags, 0},
00474 };