Commit fe2d6fe2 authored by Michael Niedermayer's avatar Michael Niedermayer

move packet interleaving function into AVOutputFormat, so it can be overriden...

move packet interleaving function into AVOutputFormat, so it can be overriden easily instead of doing reordering twice if the muxer needs some other interleaving then dts based

Originally committed as revision 3540 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent d1fb157d
......@@ -5,7 +5,7 @@
extern "C" {
#endif
#define LIBAVFORMAT_BUILD 4616
#define LIBAVFORMAT_BUILD 4617
#define LIBAVFORMAT_VERSION_INT FFMPEG_VERSION_INT
#define LIBAVFORMAT_VERSION FFMPEG_VERSION
......@@ -140,6 +140,7 @@ typedef struct AVOutputFormat {
int flags;
/* currently only used to set pixel format if not YUV420P */
int (*set_parameters)(struct AVFormatContext *, AVFormatParameters *);
int (*interleave_packet)(struct AVFormatContext *, AVPacket *out, AVPacket *in, int flush);
/* private fields */
struct AVOutputFormat *next;
} AVOutputFormat;
......
......@@ -1976,32 +1976,15 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt)
}
/**
* Writes a packet to an output media file ensuring correct interleaving.
* The packet shall contain one audio or video frame.
* If the packets are already correctly interleaved the application should
* call av_write_frame() instead as its slightly faster, its also important
* to keep in mind that non interlaved input will need huge amounts
* of memory to interleave with this, so its prefereable to interleave at the
* demuxer level
*
* @param s media file handle
* @param pkt the packet, which contains the stream_index, buf/buf_size, dts/pts, ...
* @return < 0 if error, = 0 if OK, 1 if end of stream wanted.
* interleave_packet implementation which will interleave per DTS.
*/
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){
static int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush){
AVPacketList *pktl, **next_point, *this_pktl;
int stream_count=0;
int streams[MAX_STREAMS];
AVStream *st= s->streams[ pkt->stream_index];
compute_pkt_fields2(st, pkt);
//FIXME/XXX/HACK drop zero sized packets
if(st->codec.codec_type == CODEC_TYPE_AUDIO && pkt->size==0)
return 0;
if(pkt->dts == AV_NOPTS_VALUE)
return -1;
if(pkt){
AVStream *st= s->streams[ pkt->stream_index];
assert(pkt->destruct != av_destruct_packet); //FIXME
......@@ -2020,6 +2003,7 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){
}
this_pktl->next= *next_point;
*next_point= this_pktl;
}
memset(streams, 0, sizeof(streams));
pktl= s->packet_buffer;
......@@ -2031,25 +2015,75 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){
pktl= pktl->next;
}
while(s->nb_streams == stream_count){
int ret;
if(s->nb_streams == stream_count || (flush && stream_count)){
pktl= s->packet_buffer;
//av_log(s, AV_LOG_DEBUG, "write st:%d dts:%lld\n", pktl->pkt.stream_index, pktl->pkt.dts);
truncate_ts(s->streams[pktl->pkt.stream_index], &pktl->pkt);
ret= s->oformat->write_packet(s, &pktl->pkt);
*out= pktl->pkt;
s->packet_buffer= pktl->next;
if((--streams[ pktl->pkt.stream_index ]) == 0)
stream_count--;
av_free_packet(&pktl->pkt);
av_freep(&pktl);
return 1;
}else{
av_init_packet(out);
return 0;
}
}
/**
* Interleaves a AVPacket correctly so it can be muxed.
* @param out the interleaved packet will be output here
* @param in the input packet
* @param flush 1 if no further packets are available as input and all
* remaining packets should be output
* @return 1 if a packet was output, 0 if no packet could be output,
* < 0 if an error occured
*/
static int av_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, int flush){
if(s->oformat->interleave_packet)
return s->oformat->interleave_packet(s, out, in, flush);
else
return av_interleave_packet_per_dts(s, out, in, flush);
}
/**
* Writes a packet to an output media file ensuring correct interleaving.
* The packet shall contain one audio or video frame.
* If the packets are already correctly interleaved the application should
* call av_write_frame() instead as its slightly faster, its also important
* to keep in mind that completly non interleaved input will need huge amounts
* of memory to interleave with this, so its prefereable to interleave at the
* demuxer level
*
* @param s media file handle
* @param pkt the packet, which contains the stream_index, buf/buf_size, dts/pts, ...
* @return < 0 if error, = 0 if OK, 1 if end of stream wanted.
*/
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){
AVStream *st= s->streams[ pkt->stream_index];
compute_pkt_fields2(st, pkt);
//FIXME/XXX/HACK drop zero sized packets
if(st->codec.codec_type == CODEC_TYPE_AUDIO && pkt->size==0)
return 0;
if(pkt->dts == AV_NOPTS_VALUE)
return -1;
for(;;){
AVPacket opkt;
int ret= av_interleave_packet(s, &opkt, pkt, 0);
if(ret<=0) //FIXME cleanup needed for ret<0 ?
return ret;
truncate_ts(s->streams[opkt.stream_index], &opkt);
ret= s->oformat->write_packet(s, &opkt);
av_free_packet(&opkt);
pkt= NULL;
if(ret<0)
return ret;
}
return 0;
}
/**
......@@ -2062,18 +2096,18 @@ int av_write_trailer(AVFormatContext *s)
{
int ret;
while(s->packet_buffer){
int ret;
AVPacketList *pktl= s->packet_buffer;
//av_log(s, AV_LOG_DEBUG, "write_trailer st:%d dts:%lld\n", pktl->pkt.stream_index, pktl->pkt.dts);
truncate_ts(s->streams[pktl->pkt.stream_index], &pktl->pkt);
ret= s->oformat->write_packet(s, &pktl->pkt);
for(;;){
AVPacket pkt;
ret= av_interleave_packet(s, &pkt, NULL, 1);
if(ret<0) //FIXME cleanup needed for ret<0 ?
return ret;
if(!ret)
break;
s->packet_buffer= pktl->next;
truncate_ts(s->streams[pkt.stream_index], &pkt);
ret= s->oformat->write_packet(s, &pkt);
av_free_packet(&pktl->pkt);
av_freep(&pktl);
av_free_packet(&pkt);
if(ret<0)
return ret;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment