* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-//#define DEBUG
-
#include "libavutil/attributes.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/bswap.h"
#include "libavutil/common.h"
#include "libavutil/dict.h"
+#include "libavutil/internal.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "avformat.h"
#define print_guid(g)
#endif
-void ff_get_guid(AVIOContext *s, ff_asf_guid *g)
-{
- assert(sizeof(*g) == 16);
- avio_read(s, *g, sizeof(*g));
-}
-
static int asf_probe(AVProbeData *pd)
{
/* check file header */
static int asf_read_marker(AVFormatContext *s, int64_t size)
{
AVIOContext *pb = s->pb;
+ ASFContext *asf = s->priv_data;
int i, count, name_len, ret;
char name[1024];
avio_rl64(pb); // offset, 8 bytes
pres_time = avio_rl64(pb); // presentation time
+ pres_time -= asf->hdr.preroll * 10000;
avio_rl16(pb); // entry length
avio_rl32(pb); // send time
avio_rl32(pb); // flags
if (ret < 0)
return ret;
} else if (!ff_guidcmp(&g, &ff_asf_stream_header)) {
- asf_read_stream_properties(s, gsize);
+ int ret = asf_read_stream_properties(s, gsize);
+ if (ret < 0)
+ return ret;
} else if (!ff_guidcmp(&g, &ff_asf_comment_header)) {
asf_read_content_desc(s, gsize);
} else if (!ff_guidcmp(&g, &ff_asf_language_guid)) {
* @param pb context to read data from
* @return 0 on success, <0 on error
*/
-static int ff_asf_get_packet(AVFormatContext *s, AVIOContext *pb)
+static int asf_get_packet(AVFormatContext *s, AVIOContext *pb)
{
ASFContext *asf = s->priv_data;
uint32_t packet_length, padsize;
* @return 0 if data was stored in pkt, <0 on error or 1 if more ASF
* packets need to be loaded (through asf_get_packet())
*/
-static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt)
+static int asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt)
{
ASFContext *asf = s->priv_data;
ASFStream *asf_st = 0;
asf_st = asf->asf_st;
av_assert0(asf_st);
+ if (!asf_st->frag_offset && asf->packet_frag_offset) {
+ av_dlog(s, "skipping asf data pkt with fragment offset for "
+ "stream:%d, expected:%d but got %d from pkt)\n",
+ asf->stream_index, asf_st->frag_offset,
+ asf->packet_frag_offset);
+ avio_skip(pb, asf->packet_frag_size);
+ asf->packet_size_left -= asf->packet_frag_size;
+ continue;
+ }
+
if (asf->packet_replic_size == 1) {
// frag_offset is here used as the beginning timestamp
asf->packet_frag_timestamp = asf->packet_time_start;
asf_st->ds_span);
} else {
/* packet descrambling */
- uint8_t *newdata = av_malloc(asf_st->pkt.size +
- FF_INPUT_BUFFER_PADDING_SIZE);
- if (newdata) {
+ AVBufferRef *buf = av_buffer_alloc(asf_st->pkt.size +
+ FF_INPUT_BUFFER_PADDING_SIZE);
+ if (buf) {
+ uint8_t *newdata = buf->data;
int offset = 0;
memset(newdata + asf_st->pkt.size, 0,
FF_INPUT_BUFFER_PADDING_SIZE);
asf_st->ds_chunk_size);
offset += asf_st->ds_chunk_size;
}
- av_free(asf_st->pkt.data);
- asf_st->pkt.data = newdata;
+ av_buffer_unref(&asf_st->pkt.buf);
+ asf_st->pkt.buf = buf;
+ asf_st->pkt.data = buf->data;
}
}
}
asf_st->frag_offset = 0;
*pkt = asf_st->pkt;
+#if FF_API_DESTRUCT_PACKET
+FF_DISABLE_DEPRECATION_WARNINGS
+ asf_st->pkt.destruct = NULL;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ asf_st->pkt.buf = 0;
asf_st->pkt.size = 0;
asf_st->pkt.data = 0;
asf_st->pkt.side_data_elems = 0;
int ret;
/* parse cached packets, if any */
- if ((ret = ff_asf_parse_packet(s, s->pb, pkt)) <= 0)
+ if ((ret = asf_parse_packet(s, s->pb, pkt)) <= 0)
return ret;
- if ((ret = ff_asf_get_packet(s, s->pb)) < 0)
+ if ((ret = asf_get_packet(s, s->pb)) < 0)
assert(asf->packet_size_left < FRAME_HEADER_SIZE ||
asf->packet_segments < 1);
asf->packet_time_start = 0;
return pts;
}
-static void asf_build_simple_index(AVFormatContext *s, int stream_index)
+static int asf_build_simple_index(AVFormatContext *s, int stream_index)
{
ff_asf_guid g;
ASFContext *asf = s->priv_data;
int64_t current_pos = avio_tell(s->pb);
- int i;
+ int i, ret = 0;
avio_seek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET);
- ff_get_guid(s->pb, &g);
+ if ((ret = ff_get_guid(s->pb, &g)) < 0)
+ goto end;
/* the data object can be followed by other top-level objects,
* skip them until the simple index object is reached */
while (ff_guidcmp(&g, &index_guid)) {
int64_t gsize = avio_rl64(s->pb);
if (gsize < 24 || s->pb->eof_reached) {
- avio_seek(s->pb, current_pos, SEEK_SET);
- return;
+ goto end;
}
avio_skip(s->pb, gsize - 24);
- ff_get_guid(s->pb, &g);
+ if ((ret = ff_get_guid(s->pb, &g)) < 0)
+ goto end;
}
{
int64_t itime, last_pos = -1;
int pct, ict;
int64_t av_unused gsize = avio_rl64(s->pb);
- ff_get_guid(s->pb, &g);
+ if ((ret = ff_get_guid(s->pb, &g)) < 0)
+ goto end;
itime = avio_rl64(s->pb);
pct = avio_rl32(s->pb);
ict = avio_rl32(s->pb);
}
asf->index_read = ict > 0;
}
+end:
+ if (s->pb->eof_reached)
+ ret = 0;
avio_seek(s->pb, current_pos, SEEK_SET);
+ return ret;
}
static int asf_read_seek(AVFormatContext *s, int stream_index,
ASFContext *asf = s->priv_data;
AVStream *st = s->streams[stream_index];
int64_t pos;
- int index;
+ int index, ret = 0;
if (s->packet_size <= 0)
return -1;
return ret;
}
+ /* explicitly handle the case of seeking to 0 */
+ if (!pts) {
+ asf_reset_header(s);
+ avio_seek(s->pb, s->data_offset, SEEK_SET);
+ return 0;
+ }
+
if (!asf->index_read)
- asf_build_simple_index(s, stream_index);
+ ret = asf_build_simple_index(s, stream_index);
- if ((asf->index_read && st->index_entries)) {
+ if (!ret && asf->index_read && st->index_entries) {
index = av_index_search_timestamp(st, pts, flags);
if (index >= 0) {
/* find the position */