Commit ec20fc15 authored by Michael Niedermayer's avatar Michael Niedermayer

lavf: allow grouping packets in chunks of a user specified size and duration.

This is similar to MP4Boxs -inter
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent 31f9032b
...@@ -700,6 +700,9 @@ typedef struct AVStream { ...@@ -700,6 +700,9 @@ typedef struct AVStream {
*/ */
int stream_identifier; int stream_identifier;
int64_t interleaver_chunk_size;
int64_t interleaver_chunk_duration;
/** /**
* Stream informations used internally by av_find_stream_info() * Stream informations used internally by av_find_stream_info()
*/ */
...@@ -1086,6 +1089,22 @@ typedef struct AVFormatContext { ...@@ -1086,6 +1089,22 @@ typedef struct AVFormatContext {
*/ */
int audio_preload; int audio_preload;
/**
* Max chunk time in microseconds.
* Note, not all formats support this and unpredictable things may happen if it is used when not supported.
* - encoding: Set by user via AVOptions (NO direct access)
* - decoding: unused
*/
int max_chunk_duration;
/**
* Max chunk size in bytes
* Note, not all formats support this and unpredictable things may happen if it is used when not supported.
* - encoding: Set by user via AVOptions (NO direct access)
* - decoding: unused
*/
int max_chunk_size;
/***************************************************************** /*****************************************************************
* All fields below this line are not part of the public API. They * All fields below this line are not part of the public API. They
* may not be used outside of libavformat and can be changed and * may not be used outside of libavformat and can be changed and
......
...@@ -117,6 +117,8 @@ static const AVOption options[]={ ...@@ -117,6 +117,8 @@ static const AVOption options[]={
{"explode", "abort decoding on error recognition", 0, AV_OPT_TYPE_CONST, {.dbl = FF_ER_EXPLODE }, INT_MIN, INT_MAX, D, "fer"}, {"explode", "abort decoding on error recognition", 0, AV_OPT_TYPE_CONST, {.dbl = FF_ER_EXPLODE }, INT_MIN, INT_MAX, D, "fer"},
{"fpsprobesize", "number of frames used to probe fps", OFFSET(fps_probe_size), AV_OPT_TYPE_INT, {.dbl = -1}, -1, INT_MAX-1, D}, {"fpsprobesize", "number of frames used to probe fps", OFFSET(fps_probe_size), AV_OPT_TYPE_INT, {.dbl = -1}, -1, INT_MAX-1, D},
{"audio_preload", "microseconds by which audio packets should be interleaved earlier", OFFSET(audio_preload), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX-1, E}, {"audio_preload", "microseconds by which audio packets should be interleaved earlier", OFFSET(audio_preload), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX-1, E},
{"chunk_duration", "microseconds for each chunk", OFFSET(max_chunk_duration), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX-1, E},
{"chunk_size", "size in bytes for each chunk", OFFSET(max_chunk_size), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX-1, E},
{NULL}, {NULL},
}; };
......
...@@ -3263,10 +3263,14 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt) ...@@ -3263,10 +3263,14 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt)
return ret; return ret;
} }
#define CHUNK_START 0x1000
int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt,
int (*compare)(AVFormatContext *, AVPacket *, AVPacket *)) int (*compare)(AVFormatContext *, AVPacket *, AVPacket *))
{ {
AVPacketList **next_point, *this_pktl; AVPacketList **next_point, *this_pktl;
AVStream *st= s->streams[pkt->stream_index];
int chunked= s->max_chunk_size || s->max_chunk_duration;
this_pktl = av_mallocz(sizeof(AVPacketList)); this_pktl = av_mallocz(sizeof(AVPacketList));
if (!this_pktl) if (!this_pktl)
...@@ -3276,15 +3280,33 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, ...@@ -3276,15 +3280,33 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt,
av_dup_packet(&this_pktl->pkt); // duplicate the packet if it uses non-alloced memory av_dup_packet(&this_pktl->pkt); // duplicate the packet if it uses non-alloced memory
if(s->streams[pkt->stream_index]->last_in_packet_buffer){ if(s->streams[pkt->stream_index]->last_in_packet_buffer){
next_point = &(s->streams[pkt->stream_index]->last_in_packet_buffer->next); next_point = &(st->last_in_packet_buffer->next);
}else }else{
next_point = &s->packet_buffer; next_point = &s->packet_buffer;
}
if(*next_point){ if(*next_point){
if(chunked){
uint64_t max= av_rescale_q(s->max_chunk_duration, AV_TIME_BASE_Q, st->time_base);
if( st->interleaver_chunk_size + pkt->size <= s->max_chunk_size-1U
&& st->interleaver_chunk_duration + pkt->duration <= max-1U){
st->interleaver_chunk_size += pkt->size;
st->interleaver_chunk_duration += pkt->duration;
goto next_non_null;
}else{
st->interleaver_chunk_size =
st->interleaver_chunk_duration = 0;
this_pktl->pkt.flags |= CHUNK_START;
}
}
if(compare(s, &s->packet_buffer_end->pkt, pkt)){ if(compare(s, &s->packet_buffer_end->pkt, pkt)){
while(!compare(s, &(*next_point)->pkt, pkt)){ while( *next_point
&& ((chunked && !((*next_point)->pkt.flags&CHUNK_START))
|| !compare(s, &(*next_point)->pkt, pkt))){
next_point= &(*next_point)->next; next_point= &(*next_point)->next;
} }
if(*next_point)
goto next_non_null; goto next_non_null;
}else{ }else{
next_point = &(s->packet_buffer_end->next); next_point = &(s->packet_buffer_end->next);
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include "libavutil/avutil.h" #include "libavutil/avutil.h"
#define LIBAVFORMAT_VERSION_MAJOR 53 #define LIBAVFORMAT_VERSION_MAJOR 53
#define LIBAVFORMAT_VERSION_MINOR 23 #define LIBAVFORMAT_VERSION_MINOR 24
#define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_MICRO 0
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
......
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