diff --git a/libavformat/gxfenc.c b/libavformat/gxfenc.c index 0288c8f888..2ce99e0df3 100644 --- a/libavformat/gxfenc.c +++ b/libavformat/gxfenc.c @@ -41,6 +41,7 @@ typedef struct GXFStreamContext { int p_per_gop; int b_per_gop; int closed_gop; + int64_t current_dts; } GXFStreamContext; typedef struct GXFContext { @@ -59,7 +60,6 @@ typedef struct GXFContext { uint16_t umf_media_size; int audio_written; int sample_rate; - int field_number; int flags; AVFormatContext *fc; GXFStreamContext streams[48]; @@ -596,6 +596,7 @@ static int gxf_write_header(AVFormatContext *s) } sc->track_type = 2; sc->sample_rate = st->codec->sample_rate; + av_set_pts_info(st, 64, 1, sc->sample_rate); sc->sample_size = 16; sc->frame_rate_index = -2; sc->lines_index = -2; @@ -616,6 +617,7 @@ static int gxf_write_header(AVFormatContext *s) gxf->flags |= 0x00000040; } gxf->sample_rate = sc->sample_rate; + av_set_pts_info(st, 64, 1, sc->sample_rate); if (gxf_find_lines_index(sc) < 0) sc->lines_index = -1; sc->sample_size = st->codec->bit_rate; @@ -698,10 +700,11 @@ static int gxf_parse_mpeg_frame(GXFStreamContext *sc, const uint8_t *buf, int si static int gxf_write_media_preamble(ByteIOContext *pb, GXFContext *ctx, AVPacket *pkt, int size) { GXFStreamContext *sc = &ctx->streams[pkt->stream_index]; + int64_t dts = av_rescale(pkt->dts, ctx->sample_rate, sc->sample_rate); put_byte(pb, sc->media_type); put_byte(pb, sc->index); - put_be32(pb, ctx->field_number); + put_be32(pb, dts); if (sc->codec->codec_type == CODEC_TYPE_AUDIO) { put_be16(pb, 0); put_be16(pb, size / 2); @@ -723,7 +726,7 @@ static int gxf_write_media_preamble(ByteIOContext *pb, GXFContext *ctx, AVPacket put_be24(pb, 0); } else put_be32(pb, size); - put_be32(pb, ctx->field_number); + put_be32(pb, dts); put_byte(pb, 1); /* flags */ put_byte(pb, 0); /* reserved */ return 16; @@ -743,8 +746,6 @@ static int gxf_write_media_packet(ByteIOContext *pb, GXFContext *ctx, AVPacket * gxf_write_media_preamble(pb, ctx, pkt, pkt->size + padding); put_buffer(pb, pkt->data, pkt->size); gxf_write_padding(pb, padding); - if (sc->codec->codec_type == CODEC_TYPE_VIDEO) - ctx->field_number += 2; return updatePacketSize(pb, pos); } @@ -757,65 +758,42 @@ static int gxf_write_packet(AVFormatContext *s, AVPacket *pkt) return 0; } +static int gxf_new_audio_packet(GXFContext *gxf, GXFStreamContext *sc, AVPacket *pkt, int flush) +{ + int size = flush ? fifo_size(&sc->audio_buffer, NULL) : GXF_AUDIO_PACKET_SIZE; + + if (!size) + return 0; + av_new_packet(pkt, size); + fifo_read(&sc->audio_buffer, pkt->data, size, NULL); + pkt->stream_index = sc->index; + pkt->dts = sc->current_dts; + sc->current_dts += size / 2; /* we only support 16 bit pcm mono for now */ + return size; +} + static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush) { - AVPacketList *pktl, **next_point, *this_pktl; GXFContext *gxf = s->priv_data; - GXFStreamContext *sc; + AVPacket new_pkt; int i; - if (pkt) { - sc = &gxf->streams[pkt->stream_index]; - if (sc->codec->codec_type == CODEC_TYPE_AUDIO) { - fifo_write(&sc->audio_buffer, pkt->data, pkt->size, NULL); - } else { - this_pktl = av_mallocz(sizeof(AVPacketList)); - this_pktl->pkt = *pkt; - if(pkt->destruct == av_destruct_packet) - pkt->destruct = NULL; // non shared -> must keep original from being freed - else - av_dup_packet(&this_pktl->pkt); //shared -> must dup - next_point = &s->packet_buffer; - while(*next_point){ - AVStream *st= s->streams[ pkt->stream_index]; - AVStream *st2= s->streams[ (*next_point)->pkt.stream_index]; - int64_t left= st2->time_base.num * (int64_t)st ->time_base.den; - int64_t right= st ->time_base.num * (int64_t)st2->time_base.den; - if((*next_point)->pkt.dts * left > pkt->dts * right) //FIXME this can overflow - break; - next_point= &(*next_point)->next; + for (i = 0; i < s->nb_streams; i++) { + if (s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) { + GXFStreamContext *sc = &gxf->streams[i]; + if (pkt && pkt->stream_index == i) { + fifo_write(&sc->audio_buffer, pkt->data, pkt->size, NULL); + pkt = NULL; } - this_pktl->next = *next_point; - *next_point = this_pktl; - } - } - - if (gxf->audio_written == gxf->audio_tracks) { - if (!s->packet_buffer) { - gxf->audio_written = 0; - return 0; - } - pktl = s->packet_buffer; - *out = pktl->pkt; - s->packet_buffer = pktl->next; - av_freep(&pktl); - return 1; - } else { - for (i = 0; i < s->nb_streams; i++) { - sc = &gxf->streams[i]; - if (sc->codec->codec_type == CODEC_TYPE_AUDIO && - (flush || fifo_size(&sc->audio_buffer, NULL) >= GXF_AUDIO_PACKET_SIZE)) { - int size = flush ? fifo_size(&sc->audio_buffer, NULL) : GXF_AUDIO_PACKET_SIZE; - av_new_packet(out, size); - fifo_read(&sc->audio_buffer, out->data, size, NULL); - gxf->audio_written++; - out->stream_index = i; - return 1; + if (flush || fifo_size(&sc->audio_buffer, NULL) >= GXF_AUDIO_PACKET_SIZE) { + if (gxf_new_audio_packet(gxf, sc, &new_pkt, flush) > 0) { + pkt = &new_pkt; + break; /* add pkt right now into list */ + } } } } - av_init_packet(out); - return 0; + return av_interleave_packet_per_dts(s, out, pkt, flush); } AVOutputFormat gxf_muxer = {