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