| @@ -29,6 +29,9 @@ const uint8_t ff_w64_guid_wave[16] = { 'w', 'a', 'v', 'e', | |||||
| const uint8_t ff_w64_guid_fmt [16] = { 'f', 'm', 't', ' ', | const uint8_t ff_w64_guid_fmt [16] = { 'f', 'm', 't', ' ', | ||||
| 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; | 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; | ||||
| const uint8_t ff_w64_guid_fact[16] = { 'f', 'a', 'c', 't', | |||||
| 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; | |||||
| const uint8_t ff_w64_guid_data[16] = { 'd', 'a', 't', 'a', | const uint8_t ff_w64_guid_data[16] = { 'd', 'a', 't', 'a', | ||||
| 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; | 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; | ||||
| @@ -24,6 +24,7 @@ | |||||
| extern const uint8_t ff_w64_guid_riff[16]; | extern const uint8_t ff_w64_guid_riff[16]; | ||||
| extern const uint8_t ff_w64_guid_wave[16]; | extern const uint8_t ff_w64_guid_wave[16]; | ||||
| extern const uint8_t ff_w64_guid_fmt [16]; | extern const uint8_t ff_w64_guid_fmt [16]; | ||||
| extern const uint8_t ff_w64_guid_fact[16]; | |||||
| extern const uint8_t ff_w64_guid_data[16]; | extern const uint8_t ff_w64_guid_data[16]; | ||||
| extern const uint8_t ff_w64_guid_summarylist[16]; | extern const uint8_t ff_w64_guid_summarylist[16]; | ||||
| @@ -610,6 +610,12 @@ static int w64_read_header(AVFormatContext *s) | |||||
| avio_skip(pb, FFALIGN(size, INT64_C(8)) - size); | avio_skip(pb, FFALIGN(size, INT64_C(8)) - size); | ||||
| avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); | avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); | ||||
| } else if (!memcmp(guid, ff_w64_guid_fact, 16)) { | |||||
| int64_t samples; | |||||
| samples = avio_rl64(pb); | |||||
| if (samples > 0) | |||||
| st->duration = samples; | |||||
| } else if (!memcmp(guid, ff_w64_guid_data, 16)) { | } else if (!memcmp(guid, ff_w64_guid_data, 16)) { | ||||
| wav->data_end = avio_tell(pb) + size - 24; | wav->data_end = avio_tell(pb) + size - 24; | ||||
| @@ -263,6 +263,14 @@ static int w64_write_header(AVFormatContext *s) | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| end_guid(pb, start); | end_guid(pb, start); | ||||
| if (s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */ | |||||
| && s->pb->seekable) { | |||||
| start_guid(pb, ff_w64_guid_fact, &wav->fact_pos); | |||||
| avio_wl64(pb, 0); | |||||
| end_guid(pb, wav->fact_pos); | |||||
| } | |||||
| start_guid(pb, ff_w64_guid_data, &wav->data); | start_guid(pb, ff_w64_guid_data, &wav->data); | ||||
| return 0; | return 0; | ||||
| @@ -280,8 +288,18 @@ static int w64_write_trailer(AVFormatContext *s) | |||||
| file_size = avio_tell(pb); | file_size = avio_tell(pb); | ||||
| avio_seek(pb, 16, SEEK_SET); | avio_seek(pb, 16, SEEK_SET); | ||||
| avio_wl64(pb, file_size); | avio_wl64(pb, file_size); | ||||
| avio_seek(pb, file_size, SEEK_SET); | |||||
| if (s->streams[0]->codec->codec_tag != 0x01) { | |||||
| int64_t number_of_samples; | |||||
| number_of_samples = av_rescale(wav->maxpts - wav->minpts + wav->last_duration, | |||||
| s->streams[0]->codec->sample_rate * (int64_t)s->streams[0]->time_base.num, | |||||
| s->streams[0]->time_base.den); | |||||
| avio_seek(pb, wav->fact_pos + 24, SEEK_SET); | |||||
| avio_wl64(pb, number_of_samples); | |||||
| } | |||||
| avio_seek(pb, file_size, SEEK_SET); | |||||
| avio_flush(pb); | avio_flush(pb); | ||||
| } | } | ||||