Mercurial > libavformat.hg
comparison utils.c @ 470:334e08488ad1 libavformat
correctly interleave packets during encoding
dts/pts fixed for streamcopy
dont use coded_frame->key_frame hack in muxers, use AVPacket.flags instead
author | michael |
---|---|
date | Sat, 29 May 2004 18:50:31 +0000 |
parents | 60f897e8dd2d |
children | 3fc285cdb791 |
comparison
equal
deleted
inserted
replaced
469:6a4cc19e8d9b | 470:334e08488ad1 |
---|---|
526 return frame_size; | 526 return frame_size; |
527 } | 527 } |
528 | 528 |
529 | 529 |
530 /* return the frame duration in seconds, return 0 if not available */ | 530 /* return the frame duration in seconds, return 0 if not available */ |
531 static void compute_frame_duration(int *pnum, int *pden, | 531 static void compute_frame_duration(int *pnum, int *pden, AVStream *st, |
532 AVFormatContext *s, AVStream *st, | |
533 AVCodecParserContext *pc, AVPacket *pkt) | 532 AVCodecParserContext *pc, AVPacket *pkt) |
534 { | 533 { |
535 int frame_size; | 534 int frame_size; |
536 | 535 |
537 *pnum = 0; | 536 *pnum = 0; |
575 if(pkt->dts != AV_NOPTS_VALUE) | 574 if(pkt->dts != AV_NOPTS_VALUE) |
576 pkt->dts= lsb2full(pkt->dts, st->cur_dts, st->pts_wrap_bits); | 575 pkt->dts= lsb2full(pkt->dts, st->cur_dts, st->pts_wrap_bits); |
577 } | 576 } |
578 | 577 |
579 if (pkt->duration == 0) { | 578 if (pkt->duration == 0) { |
580 compute_frame_duration(&num, &den, s, st, pc, pkt); | 579 compute_frame_duration(&num, &den, st, pc, pkt); |
581 if (den && num) { | 580 if (den && num) { |
582 pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num); | 581 pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num); |
583 } | 582 } |
584 } | 583 } |
585 | 584 |
602 if(st->cur_dts == AV_NOPTS_VALUE){ | 601 if(st->cur_dts == AV_NOPTS_VALUE){ |
603 if(presentation_delayed) st->cur_dts = -pkt->duration; | 602 if(presentation_delayed) st->cur_dts = -pkt->duration; |
604 else st->cur_dts = 0; | 603 else st->cur_dts = 0; |
605 } | 604 } |
606 | 605 |
607 // av_log(NULL, AV_LOG_DEBUG, "IN delayed:%d pts:%lld, dts:%lld cur_dts:%lld\n", presentation_delayed, pkt->pts, pkt->dts, st->cur_dts); | 606 // av_log(NULL, AV_LOG_DEBUG, "IN delayed:%d pts:%lld, dts:%lld cur_dts:%lld st:%d pc:%p\n", presentation_delayed, pkt->pts, pkt->dts, st->cur_dts, pkt->stream_index, pc); |
608 /* interpolate PTS and DTS if they are not present */ | 607 /* interpolate PTS and DTS if they are not present */ |
609 if (presentation_delayed) { | 608 if (presentation_delayed) { |
610 /* DTS = decompression time stamp */ | 609 /* DTS = decompression time stamp */ |
611 /* PTS = presentation time stamp */ | 610 /* PTS = presentation time stamp */ |
612 if (pkt->dts == AV_NOPTS_VALUE) { | 611 if (pkt->dts == AV_NOPTS_VALUE) { |
1863 } | 1862 } |
1864 } | 1863 } |
1865 return 0; | 1864 return 0; |
1866 } | 1865 } |
1867 | 1866 |
1867 //FIXME merge with compute_pkt_fields | |
1868 static void compute_pkt_fields2(AVStream *st, AVPacket *pkt){ | |
1869 int b_frames = FFMAX(st->codec.has_b_frames, st->codec.max_b_frames); | |
1870 int num, den, frame_size; | |
1871 | |
1872 // av_log(NULL, AV_LOG_DEBUG, "av_write_frame: pts:%lld dts:%lld cur_dts:%lld b:%d size:%d st:%d\n", pkt->pts, pkt->dts, st->cur_dts, b_frames, pkt->size, pkt->stream_index); | |
1873 | |
1874 /* if(pkt->pts == AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE) | |
1875 return -1;*/ | |
1876 | |
1877 if(pkt->pts != AV_NOPTS_VALUE) | |
1878 pkt->pts = av_rescale(pkt->pts, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num); | |
1879 if(pkt->dts != AV_NOPTS_VALUE) | |
1880 pkt->dts = av_rescale(pkt->dts, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num); | |
1881 | |
1882 /* duration field */ | |
1883 pkt->duration = av_rescale(pkt->duration, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num); | |
1884 if (pkt->duration == 0) { | |
1885 compute_frame_duration(&num, &den, st, NULL, pkt); | |
1886 if (den && num) { | |
1887 pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num); | |
1888 } | |
1889 } | |
1890 | |
1891 //XXX/FIXME this is a temporary hack until all encoders output pts | |
1892 if((pkt->pts == 0 || pkt->pts == AV_NOPTS_VALUE) && pkt->dts == AV_NOPTS_VALUE && !b_frames){ | |
1893 pkt->dts= | |
1894 // pkt->pts= st->cur_dts; | |
1895 pkt->pts= st->pts.val; | |
1896 } | |
1897 | |
1898 //calculate dts from pts | |
1899 if(pkt->pts != AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE){ | |
1900 if(b_frames){ | |
1901 if(st->last_IP_pts == AV_NOPTS_VALUE){ | |
1902 st->last_IP_pts= -pkt->duration; | |
1903 } | |
1904 if(st->last_IP_pts < pkt->pts){ | |
1905 pkt->dts= st->last_IP_pts; | |
1906 st->last_IP_pts= pkt->pts; | |
1907 }else | |
1908 pkt->dts= pkt->pts; | |
1909 }else | |
1910 pkt->dts= pkt->pts; | |
1911 } | |
1912 | |
1913 // av_log(NULL, AV_LOG_DEBUG, "av_write_frame: pts2:%lld dts2:%lld\n", pkt->pts, pkt->dts); | |
1914 st->cur_dts= pkt->dts; | |
1915 st->pts.val= pkt->dts; | |
1916 | |
1917 /* update pts */ | |
1918 switch (st->codec.codec_type) { | |
1919 case CODEC_TYPE_AUDIO: | |
1920 frame_size = get_audio_frame_size(&st->codec, pkt->size); | |
1921 | |
1922 /* HACK/FIXME, we skip the initial 0-size packets as they are most likely equal to the encoder delay, | |
1923 but it would be better if we had the real timestamps from the encoder */ | |
1924 if (frame_size >= 0 && (pkt->size || st->pts.num!=st->pts.den>>1 || st->pts.val)) { | |
1925 av_frac_add(&st->pts, (int64_t)st->time_base.den * frame_size); | |
1926 } | |
1927 break; | |
1928 case CODEC_TYPE_VIDEO: | |
1929 av_frac_add(&st->pts, (int64_t)st->time_base.den * st->codec.frame_rate_base); | |
1930 break; | |
1931 default: | |
1932 break; | |
1933 } | |
1934 } | |
1935 | |
1936 static void truncate_ts(AVStream *st, AVPacket *pkt){ | |
1937 int64_t pts_mask = (2LL << (st->pts_wrap_bits-1)) - 1; | |
1938 | |
1939 if(pkt->dts < 0) | |
1940 pkt->dts= 0; //this happens for low_delay=0 and b frames, FIXME, needs further invstigation about what we should do here | |
1941 | |
1942 pkt->pts &= pts_mask; | |
1943 pkt->dts &= pts_mask; | |
1944 } | |
1945 | |
1868 /** | 1946 /** |
1869 * Write a packet to an output media file. The packet shall contain | 1947 * Write a packet to an output media file. The packet shall contain |
1870 * one audio or video frame. | 1948 * one audio or video frame. |
1871 * | 1949 * |
1872 * @param s media file handle | 1950 * @param s media file handle |
1873 * @param pkt the packet, which contains the stream_index, buf/buf_size, dts/pts, ... | 1951 * @param pkt the packet, which contains the stream_index, buf/buf_size, dts/pts, ... |
1874 * @return < 0 if error, = 0 if OK, 1 if end of stream wanted. | 1952 * @return < 0 if error, = 0 if OK, 1 if end of stream wanted. |
1875 */ | 1953 */ |
1876 int av_write_frame(AVFormatContext *s, AVPacket *pkt) | 1954 int av_write_frame(AVFormatContext *s, AVPacket *pkt) |
1877 { | 1955 { |
1878 AVStream *st; | 1956 compute_pkt_fields2(s->streams[pkt->stream_index], pkt); |
1879 int64_t pts_mask; | 1957 |
1880 int ret, frame_size; | 1958 truncate_ts(s->streams[pkt->stream_index], pkt); |
1881 int b_frames; | 1959 |
1882 | 1960 return s->oformat->write_packet(s, pkt); |
1883 if(pkt->stream_index<0) | 1961 } |
1962 | |
1963 /** | |
1964 * Writes a packet to an output media file ensuring correct interleaving. | |
1965 * The packet shall contain one audio or video frame. | |
1966 * If the packets are already correctly interleaved the application should | |
1967 * call av_write_frame() instead as its slightly faster, its also important | |
1968 * to keep in mind that non interlaved input will need huge amounts | |
1969 * of memory to interleave with this, so its prefereable to interleave at the | |
1970 * demuxer level | |
1971 * | |
1972 * @param s media file handle | |
1973 * @param pkt the packet, which contains the stream_index, buf/buf_size, dts/pts, ... | |
1974 * @return < 0 if error, = 0 if OK, 1 if end of stream wanted. | |
1975 */ | |
1976 int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){ | |
1977 AVPacketList *pktl, **next_point, *this_pktl; | |
1978 int stream_count=0; | |
1979 int streams[MAX_STREAMS]; | |
1980 AVStream *st= s->streams[ pkt->stream_index]; | |
1981 | |
1982 compute_pkt_fields2(st, pkt); | |
1983 | |
1984 if(pkt->dts == AV_NOPTS_VALUE) | |
1884 return -1; | 1985 return -1; |
1885 st = s->streams[pkt->stream_index]; | 1986 |
1886 | 1987 assert(pkt->destruct != av_destruct_packet); //FIXME |
1887 b_frames = FFMAX(st->codec.has_b_frames, st->codec.max_b_frames); | 1988 |
1888 | 1989 this_pktl = av_mallocz(sizeof(AVPacketList)); |
1889 // av_log(s, AV_LOG_DEBUG, "av_write_frame: pts:%lld dts:%lld cur_dts:%lld b:%d size:%d\n", pkt->pts, pkt->dts, st->cur_dts, b_frames, pkt->size); | 1990 this_pktl->pkt= *pkt; |
1890 | 1991 av_dup_packet(&this_pktl->pkt); |
1891 /* if(pkt->pts == AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE) | 1992 |
1892 return -1;*/ | 1993 next_point = &s->packet_buffer; |
1893 | 1994 while(*next_point){ |
1894 if(pkt->pts != AV_NOPTS_VALUE) | 1995 AVStream *st2= s->streams[ (*next_point)->pkt.stream_index]; |
1895 pkt->pts = av_rescale(pkt->pts, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num); | 1996 int64_t left= st2->time_base.num * st ->time_base.den; |
1896 if(pkt->dts != AV_NOPTS_VALUE) | 1997 int64_t right= st ->time_base.num * st2->time_base.den; |
1897 pkt->dts = av_rescale(pkt->dts, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num); | 1998 if((*next_point)->pkt.dts * left > pkt->dts * right) //FIXME this can overflow |
1898 | 1999 break; |
1899 /* duration field */ | 2000 next_point= &(*next_point)->next; |
1900 pkt->duration = av_rescale(pkt->duration, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num); | 2001 } |
1901 | 2002 this_pktl->next= *next_point; |
1902 //XXX/FIXME this is a temporary hack until all encoders output pts | 2003 *next_point= this_pktl; |
1903 if((pkt->pts == 0 || pkt->pts == AV_NOPTS_VALUE) && pkt->dts == AV_NOPTS_VALUE && !b_frames){ | 2004 |
1904 pkt->dts= | 2005 memset(streams, 0, sizeof(streams)); |
1905 // pkt->pts= st->cur_dts; | 2006 pktl= s->packet_buffer; |
1906 pkt->pts= st->pts.val; | 2007 while(pktl){ |
1907 } | 2008 //av_log(s, AV_LOG_DEBUG, "show st:%d dts:%lld\n", pktl->pkt.stream_index, pktl->pkt.dts); |
1908 | 2009 if(streams[ pktl->pkt.stream_index ] == 0) |
1909 //calculate dts from pts | 2010 stream_count++; |
1910 if(pkt->pts != AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE){ | 2011 streams[ pktl->pkt.stream_index ]++; |
1911 if(b_frames){ | 2012 pktl= pktl->next; |
1912 if(st->last_IP_pts == AV_NOPTS_VALUE){ | 2013 } |
1913 st->last_IP_pts= -av_rescale(1, | 2014 |
1914 st->codec.frame_rate_base*(int64_t)st->time_base.den, | 2015 while(s->nb_streams == stream_count){ |
1915 st->codec.frame_rate *(int64_t)st->time_base.num); | 2016 int ret; |
1916 } | 2017 |
1917 if(st->last_IP_pts < pkt->pts){ | 2018 pktl= s->packet_buffer; |
1918 pkt->dts= st->last_IP_pts; | 2019 //av_log(s, AV_LOG_DEBUG, "write st:%d dts:%lld\n", pktl->pkt.stream_index, pktl->pkt.dts); |
1919 st->last_IP_pts= pkt->pts; | 2020 truncate_ts(s->streams[pktl->pkt.stream_index], &pktl->pkt); |
1920 }else | 2021 ret= s->oformat->write_packet(s, &pktl->pkt); |
1921 pkt->dts= pkt->pts; | 2022 |
1922 }else | 2023 s->packet_buffer= pktl->next; |
1923 pkt->dts= pkt->pts; | 2024 if((--streams[ pktl->pkt.stream_index ]) == 0) |
1924 } | 2025 stream_count--; |
1925 | 2026 |
1926 // av_log(s, AV_LOG_DEBUG, "av_write_frame: pts2:%lld dts2:%lld\n", pkt->pts, pkt->dts); | 2027 av_free_packet(&pktl->pkt); |
1927 st->cur_dts= pkt->dts; | 2028 av_freep(&pktl); |
1928 st->pts.val= pkt->dts; | 2029 |
1929 | 2030 if(ret<0) |
1930 pts_mask = (2LL << (st->pts_wrap_bits-1)) - 1; | 2031 return ret; |
1931 pkt->pts &= pts_mask; | 2032 } |
1932 pkt->dts &= pts_mask; | 2033 return 0; |
1933 | |
1934 ret = s->oformat->write_packet(s, pkt); | |
1935 | |
1936 if (ret < 0) | |
1937 return ret; | |
1938 | |
1939 /* update pts */ | |
1940 switch (st->codec.codec_type) { | |
1941 case CODEC_TYPE_AUDIO: | |
1942 frame_size = get_audio_frame_size(&st->codec, pkt->size); | |
1943 | |
1944 /* HACK/FIXME, we skip the initial 0-size packets as they are most likely equal to the encoder delay, | |
1945 but it would be better if we had the real timestamps from the encoder */ | |
1946 if (frame_size >= 0 && (pkt->size || st->pts.num!=st->pts.den>>1 || st->pts.val)) { | |
1947 av_frac_add(&st->pts, (int64_t)st->time_base.den * frame_size); | |
1948 } | |
1949 break; | |
1950 case CODEC_TYPE_VIDEO: | |
1951 av_frac_add(&st->pts, (int64_t)st->time_base.den * st->codec.frame_rate_base); | |
1952 break; | |
1953 default: | |
1954 break; | |
1955 } | |
1956 return ret; | |
1957 } | 2034 } |
1958 | 2035 |
1959 /** | 2036 /** |
1960 * write the stream trailer to an output media file and and free the | 2037 * write the stream trailer to an output media file and and free the |
1961 * file private data. | 2038 * file private data. |
1963 * @param s media file handle | 2040 * @param s media file handle |
1964 * @return 0 if OK. AVERROR_xxx if error. */ | 2041 * @return 0 if OK. AVERROR_xxx if error. */ |
1965 int av_write_trailer(AVFormatContext *s) | 2042 int av_write_trailer(AVFormatContext *s) |
1966 { | 2043 { |
1967 int ret; | 2044 int ret; |
2045 | |
2046 while(s->packet_buffer){ | |
2047 int ret; | |
2048 AVPacketList *pktl= s->packet_buffer; | |
2049 | |
2050 //av_log(s, AV_LOG_DEBUG, "write_trailer st:%d dts:%lld\n", pktl->pkt.stream_index, pktl->pkt.dts); | |
2051 truncate_ts(s->streams[pktl->pkt.stream_index], &pktl->pkt); | |
2052 ret= s->oformat->write_packet(s, &pktl->pkt); | |
2053 | |
2054 s->packet_buffer= pktl->next; | |
2055 | |
2056 av_free_packet(&pktl->pkt); | |
2057 av_freep(&pktl); | |
2058 | |
2059 if(ret<0) | |
2060 return ret; | |
2061 } | |
2062 | |
1968 ret = s->oformat->write_trailer(s); | 2063 ret = s->oformat->write_trailer(s); |
1969 av_freep(&s->priv_data); | 2064 av_freep(&s->priv_data); |
1970 return ret; | 2065 return ret; |
1971 } | 2066 } |
1972 | 2067 |