12 #include "aviheader.h"
20 #ifdef USE_LIBAVFORMAT_SO
21 #include <ffmpeg/avformat.h>
26 extern const struct AVCodecTag
*mp_wav_taglists
[];
27 extern const struct AVCodecTag
*mp_bmp_taglists
[];
29 extern char *info_name
;
30 extern char *info_artist
;
31 extern char *info_genre
;
32 extern char *info_subject
;
33 extern char *info_copyright
;
34 extern char *info_sourceform
;
35 extern char *info_comment
;
37 void pstrcpy(char *buf
, int buf_size
, const char *str
);
40 //AVInputFormat *avif;
51 } muxer_stream_priv_t
;
53 static char *conf_format
= NULL
;
54 static int conf_allow_lavf
= 0;
55 static int mux_rate
= 0;
56 static int mux_packet_size
= 0;
57 static float mux_preload
= 0.5;
58 static float mux_max_delay
= 0.7;
60 m_option_t lavfopts_conf
[] = {
61 {"format", &(conf_format
), CONF_TYPE_STRING
, 0, 0, 0, NULL
},
62 {"i_certify_that_my_video_stream_does_not_use_b_frames", &conf_allow_lavf
, CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
63 {"muxrate", &mux_rate
, CONF_TYPE_INT
, CONF_RANGE
, 0, INT_MAX
, NULL
},
64 {"packetsize", &mux_packet_size
, CONF_TYPE_INT
, CONF_RANGE
, 0, INT_MAX
, NULL
},
65 {"preload", &mux_preload
, CONF_TYPE_FLOAT
, CONF_RANGE
, 0, INT_MAX
, NULL
},
66 {"delay", &mux_max_delay
, CONF_TYPE_FLOAT
, CONF_RANGE
, 0, INT_MAX
, NULL
},
68 {NULL
, NULL
, 0, 0, 0, 0, NULL
}
71 static int mp_open(URLContext
*h
, const char *filename
, int flags
)
76 static int mp_close(URLContext
*h
)
82 static int mp_read(URLContext
*h
, unsigned char *buf
, int size
)
84 mp_msg(MSGT_MUXER
, MSGL_WARN
, "READ %d\n", size
);
88 static int mp_write(URLContext
*h
, unsigned char *buf
, int size
)
90 muxer_t
*muxer
= (muxer_t
*)h
->priv_data
;
91 return stream_write_buffer(muxer
->stream
, buf
, size
);
94 static offset_t
mp_seek(URLContext
*h
, offset_t pos
, int whence
)
96 muxer_t
*muxer
= (muxer_t
*)h
->priv_data
;
97 if(whence
== SEEK_CUR
)
99 off_t cur
= stream_tell(muxer
->stream
);
104 else if(whence
== SEEK_END
)
107 if(stream_control(muxer
->stream
, STREAM_CTRL_GET_SIZE
, &size
) == STREAM_UNSUPORTED
|| size
< pos
)
111 mp_msg(MSGT_MUXER
, MSGL_DBG2
, "SEEK %"PRIu64
"\n", (int64_t)pos
);
112 if(!stream_seek(muxer
->stream
, pos
))
118 static URLProtocol mp_protocol
= {
128 static muxer_stream_t
* lavf_new_stream(muxer_t
*muxer
, int type
)
130 muxer_priv_t
*priv
= muxer
->priv
;
131 muxer_stream_t
*stream
;
132 muxer_stream_priv_t
*spriv
;
135 if(!muxer
|| (type
!= MUXER_TYPE_VIDEO
&& type
!= MUXER_TYPE_AUDIO
))
137 mp_msg(MSGT_MUXER
, MSGL_ERR
, "UNKNOW TYPE %d\n", type
);
141 stream
= calloc(1, sizeof(muxer_stream_t
));
144 mp_msg(MSGT_MUXER
, MSGL_ERR
, "Could not alloc muxer_stream, EXIT\n");
147 muxer
->streams
[muxer
->avih
.dwStreams
] = stream
;
148 stream
->b_buffer
= malloc(2048);
149 if(!stream
->b_buffer
)
151 mp_msg(MSGT_MUXER
, MSGL_ERR
, "Could not alloc b_buffer, EXIT\n");
155 stream
->b_buffer_size
= 2048;
156 stream
->b_buffer_ptr
= 0;
157 stream
->b_buffer_len
= 0;
159 spriv
= calloc(1, sizeof(muxer_stream_priv_t
));
165 stream
->priv
= spriv
;
167 spriv
->avstream
= av_new_stream(priv
->oc
, 1);
170 mp_msg(MSGT_MUXER
, MSGL_ERR
, "Could not alloc avstream, EXIT\n");
173 spriv
->avstream
->stream_copy
= 1;
175 ctx
= spriv
->avstream
->codec
;
176 ctx
->codec_id
= muxer
->avih
.dwStreams
;
179 case MUXER_TYPE_VIDEO
:
180 ctx
->codec_type
= CODEC_TYPE_VIDEO
;
182 case MUXER_TYPE_AUDIO
:
183 ctx
->codec_type
= CODEC_TYPE_AUDIO
;
187 muxer
->avih
.dwStreams
++;
188 stream
->muxer
= muxer
;
190 mp_msg(MSGT_MUXER
, MSGL_V
, "ALLOCATED STREAM N. %d, type=%d\n", muxer
->avih
.dwStreams
, type
);
195 static void fix_parameters(muxer_stream_t
*stream
)
197 muxer_stream_priv_t
*spriv
= (muxer_stream_priv_t
*) stream
->priv
;
200 ctx
= spriv
->avstream
->codec
;
202 ctx
->bit_rate
= stream
->avg_rate
;
203 if(stream
->wf
&& stream
->wf
->nAvgBytesPerSec
&& !ctx
->bit_rate
)
204 ctx
->bit_rate
= stream
->wf
->nAvgBytesPerSec
* 8;
205 ctx
->rc_buffer_size
= stream
->vbv_size
;
206 ctx
->rc_max_rate
= stream
->max_rate
;
208 if(stream
->type
== MUXER_TYPE_AUDIO
)
210 ctx
->codec_id
= av_codec_get_id(mp_wav_taglists
, stream
->wf
->wFormatTag
);
211 #if 0 //breaks aac in mov at least
212 ctx
->codec_tag
= codec_get_wav_tag(ctx
->codec_id
);
214 mp_msg(MSGT_MUXER
, MSGL_INFO
, "AUDIO CODEC ID: %x, TAG: %x\n", ctx
->codec_id
, (uint32_t) ctx
->codec_tag
);
215 ctx
->sample_rate
= stream
->wf
->nSamplesPerSec
;
216 // mp_msg(MSGT_MUXER, MSGL_INFO, "stream->h.dwSampleSize: %d\n", stream->h.dwSampleSize);
217 ctx
->channels
= stream
->wf
->nChannels
;
218 if(stream
->h
.dwRate
&& (stream
->h
.dwScale
* (int64_t)ctx
->sample_rate
) % stream
->h
.dwRate
== 0)
219 ctx
->frame_size
= (stream
->h
.dwScale
* (int64_t)ctx
->sample_rate
) / stream
->h
.dwRate
;
220 mp_msg(MSGT_MUXER
, MSGL_V
, "MUXER_LAVF(audio stream) frame_size: %d, scale: %u, sps: %u, rate: %u, ctx->block_align = stream->wf->nBlockAlign; %d=%d stream->wf->nAvgBytesPerSec:%d\n",
221 ctx
->frame_size
, stream
->h
.dwScale
, ctx
->sample_rate
, stream
->h
.dwRate
,
222 ctx
->block_align
, stream
->wf
->nBlockAlign
, stream
->wf
->nAvgBytesPerSec
);
223 ctx
->block_align
= stream
->h
.dwSampleSize
;
224 if(stream
->wf
+1 && stream
->wf
->cbSize
)
226 ctx
->extradata
= av_malloc(stream
->wf
->cbSize
);
227 if(ctx
->extradata
!= NULL
)
229 ctx
->extradata_size
= stream
->wf
->cbSize
;
230 memcpy(ctx
->extradata
, stream
->wf
+1, ctx
->extradata_size
);
233 mp_msg(MSGT_MUXER
, MSGL_ERR
, "MUXER_LAVF(audio stream) error! couldn't allocate %d bytes for extradata\n",
237 else if(stream
->type
== MUXER_TYPE_VIDEO
)
239 ctx
->codec_id
= av_codec_get_id(mp_bmp_taglists
, stream
->bih
->biCompression
);
240 if(ctx
->codec_id
<= 0 || force_fourcc
)
241 ctx
->codec_tag
= stream
->bih
->biCompression
;
242 mp_msg(MSGT_MUXER
, MSGL_INFO
, "VIDEO CODEC ID: %d\n", ctx
->codec_id
);
243 ctx
->width
= stream
->bih
->biWidth
;
244 ctx
->height
= stream
->bih
->biHeight
;
245 ctx
->bit_rate
= 800000;
246 ctx
->time_base
.den
= stream
->h
.dwRate
;
247 ctx
->time_base
.num
= stream
->h
.dwScale
;
248 if(stream
->bih
+1 && (stream
->bih
->biSize
> sizeof(BITMAPINFOHEADER
)))
250 ctx
->extradata_size
= stream
->bih
->biSize
- sizeof(BITMAPINFOHEADER
);
251 ctx
->extradata
= av_malloc(ctx
->extradata_size
);
252 if(ctx
->extradata
!= NULL
)
253 memcpy(ctx
->extradata
, stream
->bih
+1, ctx
->extradata_size
);
256 mp_msg(MSGT_MUXER
, MSGL_ERR
, "MUXER_LAVF(video stream) error! couldn't allocate %d bytes for extradata\n",
257 ctx
->extradata_size
);
258 ctx
->extradata_size
= 0;
264 static void write_chunk(muxer_stream_t
*stream
, size_t len
, unsigned int flags
, double dts
, double pts
)
266 muxer_t
*muxer
= (muxer_t
*) stream
->muxer
;
267 muxer_priv_t
*priv
= (muxer_priv_t
*) muxer
->priv
;
268 muxer_stream_priv_t
*spriv
= (muxer_stream_priv_t
*) stream
->priv
;
273 av_init_packet(&pkt
);
275 pkt
.stream_index
= spriv
->avstream
->index
;
276 pkt
.data
= stream
->buffer
;
278 if(flags
& AVIIF_KEYFRAME
)
279 pkt
.flags
|= PKT_FLAG_KEY
;
284 //pkt.pts = AV_NOPTS_VALUE;
285 pkt
.pts
= (stream
->timer
/ av_q2d(priv
->oc
->streams
[pkt
.stream_index
]->time_base
) + 0.5);
286 //fprintf(stderr, "%Ld %Ld id:%d tb:%f %f\n", pkt.dts, pkt.pts, pkt.stream_index, av_q2d(priv->oc->streams[pkt.stream_index]->time_base), stream->timer);
288 if(av_interleaved_write_frame(priv
->oc
, &pkt
) != 0) //av_write_frame(priv->oc, &pkt)
290 mp_msg(MSGT_MUXER
, MSGL_ERR
, "Error while writing frame\n");
298 static void write_header(muxer_t
*muxer
)
300 muxer_priv_t
*priv
= (muxer_priv_t
*) muxer
->priv
;
302 mp_msg(MSGT_MUXER
, MSGL_INFO
, MSGTR_WritingHeader
);
303 av_write_header(priv
->oc
);
304 muxer
->cont_write_header
= NULL
;
308 static void write_trailer(muxer_t
*muxer
)
311 muxer_priv_t
*priv
= (muxer_priv_t
*) muxer
->priv
;
313 mp_msg(MSGT_MUXER
, MSGL_INFO
, MSGTR_WritingTrailer
);
314 av_write_trailer(priv
->oc
);
315 for(i
= 0; i
< priv
->oc
->nb_streams
; i
++)
317 av_freep(&(priv
->oc
->streams
[i
]));
320 url_fclose(&(priv
->oc
->pb
));
325 static void list_formats(void) {
327 mp_msg(MSGT_DEMUX
, MSGL_INFO
, "Available lavf output formats:\n");
328 for (fmt
= first_oformat
; fmt
; fmt
= fmt
->next
)
329 mp_msg(MSGT_DEMUX
, MSGL_INFO
, "%15s : %s\n", fmt
->name
, fmt
->long_name
);
332 extern char *out_filename
;
333 int muxer_init_muxer_lavf(muxer_t
*muxer
)
336 AVOutputFormat
*fmt
= NULL
;
337 char mp_filename
[256] = "menc://stream.dummy";
341 if (conf_format
&& strcmp(conf_format
, "help") == 0) {
346 mp_msg(MSGT_MUXER
, MSGL_WARN
, "** MUXER_LAVF *****************************************************************\n");
347 if (!conf_allow_lavf
) {
348 mp_msg(MSGT_MUXER
, MSGL_FATAL
,
349 "If you wish to use libavformat muxing, you must ensure that your video stream\n"
350 "does not contain B frames (out of order decoding) and specify:\n"
351 " -lavfopts i_certify_that_my_video_stream_does_not_use_b_frames\n"
352 "on the command line.\n");
354 mp_msg(MSGT_MUXER
, MSGL_WARN
,
355 "You have certified that your video stream does not contain B frames.\n");
357 mp_msg(MSGT_MUXER
, MSGL_WARN
,
358 "REMEMBER: MEncoder's libavformat muxing is presently broken and will generate\n"
359 "INCORRECT files in the presence of B frames. Moreover, due to bugs MPlayer\n"
360 "will play these INCORRECT files as if nothing were wrong!\n"
361 "*******************************************************************************\n");
362 if (!conf_allow_lavf
) return 0;
364 priv
= (muxer_priv_t
*) calloc(1, sizeof(muxer_priv_t
));
368 priv
->oc
= av_alloc_format_context();
371 mp_msg(MSGT_MUXER
, MSGL_FATAL
, "Couldn't get format context\n");
376 fmt
= guess_format(conf_format
, NULL
, NULL
);
378 fmt
= guess_format(NULL
, out_filename
, NULL
);
381 mp_msg(MSGT_MUXER
, MSGL_FATAL
, "CAN'T GET SPECIFIED FORMAT\n");
384 priv
->oc
->oformat
= fmt
;
387 if(av_set_parameters(priv
->oc
, NULL
) < 0)
389 mp_msg(MSGT_MUXER
, MSGL_FATAL
, "Invalid output format parameters\n");
392 priv
->oc
->packet_size
= mux_packet_size
;
393 priv
->oc
->mux_rate
= mux_rate
;
394 priv
->oc
->preload
= (int)(mux_preload
*AV_TIME_BASE
);
395 priv
->oc
->max_delay
= (int)(mux_max_delay
*AV_TIME_BASE
);
397 pstrcpy(priv
->oc
->title
, sizeof(priv
->oc
->title
), info_name
);
399 pstrcpy(priv
->oc
->author
, sizeof(priv
->oc
->author
), info_artist
);
401 pstrcpy(priv
->oc
->genre
, sizeof(priv
->oc
->genre
), info_genre
);
403 pstrcpy(priv
->oc
->copyright
, sizeof(priv
->oc
->copyright
), info_copyright
);
405 pstrcpy(priv
->oc
->comment
, sizeof(priv
->oc
->comment
), info_comment
);
406 register_protocol(&mp_protocol
);
408 if(url_fopen(&priv
->oc
->pb
, mp_filename
, URL_WRONLY
))
410 mp_msg(MSGT_MUXER
, MSGL_FATAL
, "Coulnd't open outfile\n");
414 ((URLContext
*)(priv
->oc
->pb
.opaque
))->priv_data
= muxer
;
416 muxer
->priv
= (void *) priv
;
417 muxer
->cont_new_stream
= &lavf_new_stream
;
418 muxer
->cont_write_chunk
= &write_chunk
;
419 muxer
->cont_write_header
= &write_header
;
420 muxer
->cont_write_index
= &write_trailer
;
421 muxer
->fix_stream_parameters
= &fix_parameters
;
422 mp_msg(MSGT_MUXER
, MSGL_INFO
, "OK, exit\n");