mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-03-28 12:32:17 +02:00
lavf: add write_uncoded_frame() API.
This commit is contained in:
parent
6c12b1de06
commit
1b05ac220e
@ -512,6 +512,17 @@ typedef struct AVOutputFormat {
|
|||||||
*/
|
*/
|
||||||
int (*control_message)(struct AVFormatContext *s, int type,
|
int (*control_message)(struct AVFormatContext *s, int type,
|
||||||
void *data, size_t data_size);
|
void *data, size_t data_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write an uncoded AVFrame.
|
||||||
|
*
|
||||||
|
* See av_write_uncoded_frame() for details.
|
||||||
|
*
|
||||||
|
* The library will free *frame afterwards, but the muxer can prevent it
|
||||||
|
* by setting the pointer to NULL.
|
||||||
|
*/
|
||||||
|
int (*write_uncoded_frame)(struct AVFormatContext *, int stream_index,
|
||||||
|
AVFrame **frame, unsigned flags);
|
||||||
} AVOutputFormat;
|
} AVOutputFormat;
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
@ -2092,6 +2103,44 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt);
|
|||||||
*/
|
*/
|
||||||
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);
|
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a uncoded frame to an output media file.
|
||||||
|
*
|
||||||
|
* The frame must be correctly interleaved according to the container
|
||||||
|
* specification; if not, then av_interleaved_write_frame() must be used.
|
||||||
|
*
|
||||||
|
* See av_interleaved_write_frame() for details.
|
||||||
|
*/
|
||||||
|
int av_write_uncoded_frame(AVFormatContext *s, int stream_index,
|
||||||
|
AVFrame *frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a uncoded frame to an output media file.
|
||||||
|
*
|
||||||
|
* If the muxer supports it, this function allows to write an AVFrame
|
||||||
|
* structure directly, without encoding it into a packet.
|
||||||
|
* It is mostly useful for devices and similar special muxers that use raw
|
||||||
|
* video or PCM data and will not serialize it into a byte stream.
|
||||||
|
*
|
||||||
|
* To test whether it is possible to use it with a given muxer and stream,
|
||||||
|
* use av_write_uncoded_frame_query().
|
||||||
|
*
|
||||||
|
* The caller gives up ownership of the frame and must not access it
|
||||||
|
* afterwards.
|
||||||
|
*
|
||||||
|
* @return >=0 for success, a negative code on error
|
||||||
|
*/
|
||||||
|
int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index,
|
||||||
|
AVFrame *frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether a muxer supports uncoded frame.
|
||||||
|
*
|
||||||
|
* @return >=0 if an uncoded frame can be written to that muxer and stream,
|
||||||
|
* <0 if not
|
||||||
|
*/
|
||||||
|
int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the stream trailer to an output media file and free the
|
* Write the stream trailer to an output media file and free the
|
||||||
* file private data.
|
* file private data.
|
||||||
|
@ -398,4 +398,18 @@ int ff_rfps_add_frame(AVFormatContext *ic, AVStream *st, int64_t dts);
|
|||||||
|
|
||||||
void ff_rfps_calculate(AVFormatContext *ic);
|
void ff_rfps_calculate(AVFormatContext *ic);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags for AVFormatContext.write_uncoded_frame()
|
||||||
|
*/
|
||||||
|
enum AVWriteUncodedFrameFlags {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query whether the feature is possible on this stream.
|
||||||
|
* The frame argument is ignored.
|
||||||
|
*/
|
||||||
|
AV_WRITE_UNCODED_FRAME_QUERY = 0x0001,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* AVFORMAT_INTERNAL_H */
|
#endif /* AVFORMAT_INTERNAL_H */
|
||||||
|
@ -417,6 +417,15 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define AV_PKT_FLAG_UNCODED_FRAME 0x2000
|
||||||
|
|
||||||
|
/* Note: using sizeof(AVFrame) from outside lavu is unsafe in general, but
|
||||||
|
it is only being used internally to this file as a consistency check.
|
||||||
|
The value is chosen to be very unlikely to appear on its own and to cause
|
||||||
|
immediate failure if used anywhere as a real size. */
|
||||||
|
#define UNCODED_FRAME_PACKET_SIZE (INT_MIN / 3 * 2 + (int)sizeof(AVFrame))
|
||||||
|
|
||||||
|
|
||||||
//FIXME merge with compute_pkt_fields
|
//FIXME merge with compute_pkt_fields
|
||||||
static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
|
static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
|
||||||
{
|
{
|
||||||
@ -482,7 +491,9 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
|
|||||||
/* update pts */
|
/* update pts */
|
||||||
switch (st->codec->codec_type) {
|
switch (st->codec->codec_type) {
|
||||||
case AVMEDIA_TYPE_AUDIO:
|
case AVMEDIA_TYPE_AUDIO:
|
||||||
frame_size = ff_get_audio_frame_size(st->codec, pkt->size, 1);
|
frame_size = (pkt->flags & AV_PKT_FLAG_UNCODED_FRAME) ?
|
||||||
|
((AVFrame *)pkt->data)->nb_samples :
|
||||||
|
ff_get_audio_frame_size(st->codec, pkt->size, 1);
|
||||||
|
|
||||||
/* HACK/FIXME, we skip the initial 0 size packets as they are most
|
/* HACK/FIXME, we skip the initial 0 size packets as they are most
|
||||||
* likely equal to the encoder delay, but it would be better if we
|
* likely equal to the encoder delay, but it would be better if we
|
||||||
@ -549,7 +560,14 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
did_split = av_packet_split_side_data(pkt);
|
did_split = av_packet_split_side_data(pkt);
|
||||||
|
if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) {
|
||||||
|
AVFrame *frame = (AVFrame *)pkt->data;
|
||||||
|
av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE);
|
||||||
|
ret = s->oformat->write_uncoded_frame(s, pkt->stream_index, &frame, 0);
|
||||||
|
av_frame_free(&frame);
|
||||||
|
} else {
|
||||||
ret = s->oformat->write_packet(s, pkt);
|
ret = s->oformat->write_packet(s, pkt);
|
||||||
|
}
|
||||||
|
|
||||||
if (s->flush_packets && s->pb && ret >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
|
if (s->flush_packets && s->pb && ret >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
|
||||||
avio_flush(s->pb);
|
avio_flush(s->pb);
|
||||||
@ -632,8 +650,13 @@ FF_DISABLE_DEPRECATION_WARNINGS
|
|||||||
FF_ENABLE_DEPRECATION_WARNINGS
|
FF_ENABLE_DEPRECATION_WARNINGS
|
||||||
#endif
|
#endif
|
||||||
pkt->buf = NULL;
|
pkt->buf = NULL;
|
||||||
|
if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) {
|
||||||
|
av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE);
|
||||||
|
av_assert0(((AVFrame *)pkt->data)->buf);
|
||||||
|
} else {
|
||||||
av_dup_packet(&this_pktl->pkt); // duplicate the packet if it uses non-allocated memory
|
av_dup_packet(&this_pktl->pkt); // duplicate the packet if it uses non-allocated memory
|
||||||
av_copy_packet_side_data(&this_pktl->pkt, &this_pktl->pkt); // copy side data
|
av_copy_packet_side_data(&this_pktl->pkt, &this_pktl->pkt); // copy side data
|
||||||
|
}
|
||||||
|
|
||||||
if (s->streams[pkt->stream_index]->last_in_packet_buffer) {
|
if (s->streams[pkt->stream_index]->last_in_packet_buffer) {
|
||||||
next_point = &(st->last_in_packet_buffer->next);
|
next_point = &(st->last_in_packet_buffer->next);
|
||||||
@ -932,3 +955,51 @@ int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt,
|
|||||||
dst->streams[dst_stream]->time_base);
|
dst->streams[dst_stream]->time_base);
|
||||||
return av_write_frame(dst, &local_pkt);
|
return av_write_frame(dst, &local_pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int av_write_uncoded_frame_internal(AVFormatContext *s, int stream_index,
|
||||||
|
AVFrame *frame, int interleaved)
|
||||||
|
{
|
||||||
|
AVPacket pkt, *pktp;
|
||||||
|
|
||||||
|
av_assert0(s->oformat);
|
||||||
|
if (!s->oformat->write_uncoded_frame)
|
||||||
|
return AVERROR(ENOSYS);
|
||||||
|
|
||||||
|
if (!frame) {
|
||||||
|
pktp = NULL;
|
||||||
|
} else {
|
||||||
|
pktp = &pkt;
|
||||||
|
av_init_packet(&pkt);
|
||||||
|
pkt.data = (void *)frame;
|
||||||
|
pkt.size = UNCODED_FRAME_PACKET_SIZE;
|
||||||
|
pkt.pts =
|
||||||
|
pkt.dts = frame->pts;
|
||||||
|
pkt.duration = av_frame_get_pkt_duration(frame);
|
||||||
|
pkt.stream_index = stream_index;
|
||||||
|
pkt.flags |= AV_PKT_FLAG_UNCODED_FRAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
return interleaved ? av_interleaved_write_frame(s, pktp) :
|
||||||
|
av_write_frame(s, pktp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int av_write_uncoded_frame(AVFormatContext *s, int stream_index,
|
||||||
|
AVFrame *frame)
|
||||||
|
{
|
||||||
|
return av_write_uncoded_frame_internal(s, stream_index, frame, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index,
|
||||||
|
AVFrame *frame)
|
||||||
|
{
|
||||||
|
return av_write_uncoded_frame_internal(s, stream_index, frame, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index)
|
||||||
|
{
|
||||||
|
av_assert0(s->oformat);
|
||||||
|
if (!s->oformat->write_uncoded_frame)
|
||||||
|
return AVERROR(ENOSYS);
|
||||||
|
return s->oformat->write_uncoded_frame(s, stream_index, NULL,
|
||||||
|
AV_WRITE_UNCODED_FRAME_QUERY);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user