History

avformat/matroskaenc: Split updating CodecPrivate from writing it

Up until now, updating extradata was very ad-hoc: The amount of space reserved for extradata was not recorded when writing the header; instead the AAC code simply presumed that it was enough. This commit changes this by recording how much space is available. This brings with it that the code for writing of and reserving space for the CodecPrivate and for updating it diverges. They are therefore split; this allows to put other common tasks like seeking to right offset as well as writing padding (in case the new extradata did not fill the whole reserved space) to this common function. The code for filling up the reserved space is smarter than the code it replaces; therefore it is no longer necessary to reserve more than necessary just to be sure that one can add an EBML Void element (whose minimum size is two) lateron. This is the reason for the change to the aac-autobsf-adtstoasc test.

Andreas Rheinhardt committed 4 years ago

Commit 67eea6c1 parent 3a00a1a2 files · +84 −40Browse files

Unified · Split

2 files
  1. libavformat/matroskaenc.c +82 −38
  2. tests/ref/fate/aac-autobsf-adtstoasc +2 −2
libavformat/matroskaenc.c+82−38
@@ -184,7 +184,8 @@ typedef struct mkv_track { · 183 unmodified lines
184 int64_t last_timestamp;184 int64_t last_timestamp;
185 int64_t duration;185 int64_t duration;
186 int64_t duration_offset;186 int64_t duration_offset;
187 int64_t codecpriv_offset;187 int codecpriv_offset;
188 unsigned codecpriv_size; ///< size reserved for CodecPrivate excluding header+length field
188 int64_t ts_offset;189 int64_t ts_offset;
189 /* This callback will be called twice: First with a NULL AVIOContext190 /* This callback will be called twice: First with a NULL AVIOContext
190 * to return the size of the (Simple)Block's data via size191 * to return the size of the (Simple)Block's data via size
@@ -1116,7 +1117,7 @@ static int mkv_assemble_native_codecprivate(AVFormatContext *s, AVIOContext *dyn · 925 unmodified lines
1116 return ff_isom_write_av1c(dyn_cp, extradata,1117 return ff_isom_write_av1c(dyn_cp, extradata,
1117 extradata_size, 1);1118 extradata_size, 1);
1118 else1119 else
1119 *size_to_reserve = 4 + 3;1120 *size_to_reserve = 4;
1120 break;1121 break;
1121#if CONFIG_MATROSKA_MUXER1122#if CONFIG_MATROSKA_MUXER
1122 case AV_CODEC_ID_FLAC:1123 case AV_CODEC_ID_FLAC:
@@ -1143,7 +1144,7 @@ static int mkv_assemble_native_codecprivate(AVFormatContext *s, AVIOContext *dyn · 20 unmodified lines
1143 if (extradata_size)1144 if (extradata_size)
1144 avio_write(dyn_cp, extradata, extradata_size);1145 avio_write(dyn_cp, extradata, extradata_size);
1145 else1146 else
1146 *size_to_reserve = 4 + MAX_PCE_SIZE + 2;1147 *size_to_reserve = MAX_PCE_SIZE;
1147 break;1148 break;
1148#endif1149#endif
1149 default:1150 default:
@@ -1162,17 +1163,16 @@ static int mkv_assemble_codecprivate(AVFormatContext *s, AVIOContext *dyn_cp, · 12 unmodified lines
1162 const uint8_t *extradata, int extradata_size,1163 const uint8_t *extradata, int extradata_size,
1163 int native_id, int qt_id,1164 int native_id, int qt_id,
1164 uint8_t **codecpriv, int *codecpriv_size,1165 uint8_t **codecpriv, int *codecpriv_size,
1165 unsigned *size_to_reserve)1166 unsigned *max_payload_size)
1166{1167{
1167 MatroskaMuxContext av_unused *const mkv = s->priv_data;1168 MatroskaMuxContext av_unused *const mkv = s->priv_data;
1169 unsigned size_to_reserve = 0;
1168 int ret;1170 int ret;
1169 1171
1170 *size_to_reserve = 0;
1171
1172 if (native_id) {1172 if (native_id) {
1173 ret = mkv_assemble_native_codecprivate(s, dyn_cp, par,1173 ret = mkv_assemble_native_codecprivate(s, dyn_cp, par,
1174 extradata, extradata_size,1174 extradata, extradata_size,
1175 size_to_reserve);1175 &size_to_reserve);
1176 if (ret < 0)1176 if (ret < 0)
1177 return ret;1177 return ret;
1178#if CONFIG_MATROSKA_MUXER1178#if CONFIG_MATROSKA_MUXER
@@ -1226,31 +1226,72 @@ static int mkv_assemble_codecprivate(AVFormatContext *s, AVIOContext *dyn_cp, · 47 unmodified lines
1226 *codecpriv_size = avio_get_dyn_buf(dyn_cp, codecpriv);1226 *codecpriv_size = avio_get_dyn_buf(dyn_cp, codecpriv);
1227 if (dyn_cp->error < 0)1227 if (dyn_cp->error < 0)
1228 return dyn_cp->error;1228 return dyn_cp->error;
1229 *max_payload_size = *codecpriv_size + size_to_reserve;
1230
1229 return 0;1231 return 0;
1230}1232}
1231 1233
1232static int mkv_write_codecprivate(AVFormatContext *s, MatroskaMuxContext *mkv,1234static void mkv_put_codecprivate(AVIOContext *pb, unsigned max_payload_size,
1233 AVCodecParameters *par,1235 const uint8_t *codecpriv, unsigned codecpriv_size)
1234 const uint8_t *extradata, int extradata_size,1236{
1235 int native_id, int qt_id, AVIOContext *pb)1237 unsigned total_codecpriv_size = 0, total_size;
1238
1239 av_assert1(codecpriv_size <= max_payload_size);
1240
1241 if (!max_payload_size)
1242 return;
1243
1244 total_size = 2 + ebml_length_size(max_payload_size) + max_payload_size;
1245
1246 if (codecpriv_size) {
1247 unsigned length_size = ebml_length_size(codecpriv_size);
1248
1249 total_codecpriv_size = 2U + length_size + codecpriv_size;
1250 if (total_codecpriv_size + 1 == total_size) {
1251 /* It is impossible to add one byte of padding via an EBML Void. */
1252 length_size++;
1253 total_codecpriv_size++;
1254 }
1255 put_ebml_id(pb, MATROSKA_ID_CODECPRIVATE);
1256 put_ebml_length(pb, codecpriv_size, length_size);
1257 avio_write(pb, codecpriv, codecpriv_size);
1258 }
1259 if (total_codecpriv_size < total_size)
1260 put_ebml_void(pb, total_size - total_codecpriv_size);
1261}
1262
1263static int mkv_update_codecprivate(AVFormatContext *s, MatroskaMuxContext *mkv,
1264 uint8_t *side_data, int side_data_size,
1265 AVCodecParameters *par, AVIOContext *pb,
1266 mkv_track *track)
1236{1267{
1237 AVIOContext *const dyn_bc = mkv->tmp_bc;1268 AVIOContext *const dyn_bc = mkv->tmp_bc;
1238 uint8_t *codecpriv;1269 uint8_t *codecpriv;
1239 unsigned size_to_reserve;1270 unsigned max_payload_size;
1240 int ret, codecpriv_size;1271 int ret, codecpriv_size;
1241 1272
1242 ret = mkv_assemble_codecprivate(s, dyn_bc, par, extradata, extradata_size,1273 ret = mkv_assemble_codecprivate(s, dyn_bc, par,
1243 native_id, qt_id,1274 side_data, side_data_size, 1, 0,
1244 &codecpriv, &codecpriv_size, &size_to_reserve);1275 &codecpriv, &codecpriv_size, &max_payload_size);
1245 if (ret < 0)1276 if (ret < 0)
1246 goto end;1277 goto fail;
1247 if (codecpriv_size)1278 if (codecpriv_size > track->codecpriv_size) {
1248 put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codecpriv, codecpriv_size);1279 ret = AVERROR(ENOSPC);
1249 if (size_to_reserve)1280 goto fail;
1250 put_ebml_void(pb, size_to_reserve);1281 }
1251end:1282 avio_seek(pb, track->codecpriv_offset, SEEK_SET);
1283 mkv_put_codecprivate(pb, track->codecpriv_size,
1284 codecpriv, codecpriv_size);
1285
1286 if (!par->extradata_size) {
1287 ret = ff_alloc_extradata(par, side_data_size);
1288 if (ret < 0)
1289 goto fail;
1290 memcpy(par->extradata, side_data, side_data_size);
1291 }
1292fail:
1252 ffio_reset_dyn_buf(dyn_bc);1293 ffio_reset_dyn_buf(dyn_bc);
1253 return 0;1294 return ret;
1254}1295}
1255 1296
1256#define MAX_VIDEO_COLOR_ELEMS 201297#define MAX_VIDEO_COLOR_ELEMS 20
@@ -1862,16 +1903,24 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, · 605 unmodified lines
1862 }1903 }
1863 1904
1864 if (!IS_WEBM(mkv) || par->codec_id != AV_CODEC_ID_WEBVTT) {1905 if (!IS_WEBM(mkv) || par->codec_id != AV_CODEC_ID_WEBVTT) {
1906 uint8_t *codecpriv;
1907 int codecpriv_size, max_payload_size;
1865 track->codecpriv_offset = avio_tell(pb);1908 track->codecpriv_offset = avio_tell(pb);
1866 ret = mkv_write_codecprivate(s, mkv, par, par->extradata, par->extradata_size,1909 ret = mkv_assemble_codecprivate(s, mkv->tmp_bc, par,
1867 native_id, qt_id, pb);1910 par->extradata, par->extradata_size,
1911 native_id, qt_id,
1912 &codecpriv, &codecpriv_size, &max_payload_size);
1868 if (ret < 0)1913 if (ret < 0)
1869 return ret;1914 goto fail;
1915 mkv_put_codecprivate(pb, max_payload_size, codecpriv, codecpriv_size);
1916 track->codecpriv_size = max_payload_size;
1870 }1917 }
1871 1918
1872 end_ebml_master(pb, track_master);1919 end_ebml_master(pb, track_master);
1920fail:
1921 ffio_reset_dyn_buf(mkv->tmp_bc);
1873 1922
1874 return 0;1923 return ret;
1875}1924}
1876 1925
1877static int mkv_write_tracks(AVFormatContext *s)1926static int mkv_write_tracks(AVFormatContext *s)
@@ -2645,23 +2694,17 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) · 767 unmodified lines
2645#if CONFIG_MATROSKA_MUXER2694#if CONFIG_MATROSKA_MUXER
2646 case AV_CODEC_ID_AAC:2695 case AV_CODEC_ID_AAC:
2647 if (side_data_size && mkv->track.bc) {2696 if (side_data_size && mkv->track.bc) {
2648 int filler, output_sample_rate = 0;2697 int output_sample_rate = 0;
2649 ret = get_aac_sample_rates(s, mkv, side_data, side_data_size,2698 ret = get_aac_sample_rates(s, mkv, side_data, side_data_size,
2650 &track->sample_rate, &output_sample_rate);2699 &track->sample_rate, &output_sample_rate);
2651 if (ret < 0)2700 if (ret < 0)
2652 return ret;2701 return ret;
2653 if (!output_sample_rate)2702 if (!output_sample_rate)
2654 output_sample_rate = track->sample_rate; // Space is already reserved, so it's this or a void element.2703 output_sample_rate = track->sample_rate; // Space is already reserved, so it's this or a void element.
2655 ret = ff_alloc_extradata(par, side_data_size);2704 ret = mkv_update_codecprivate(s, mkv, side_data, side_data_size,
2705 par, mkv->track.bc, track);
2656 if (ret < 0)2706 if (ret < 0)
2657 return ret;2707 return ret;
2658 memcpy(par->extradata, side_data, side_data_size);
2659 avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET);
2660 mkv_write_codecprivate(s, mkv, par, side_data, side_data_size,
2661 1, 0, mkv->track.bc);
2662 filler = MAX_PCE_SIZE + 2 + 4 - (avio_tell(mkv->track.bc) - track->codecpriv_offset);
2663 if (filler)
2664 put_ebml_void(mkv->track.bc, filler);
2665 avio_seek(mkv->track.bc, track->sample_rate_offset, SEEK_SET);2708 avio_seek(mkv->track.bc, track->sample_rate_offset, SEEK_SET);
2666 put_ebml_float(mkv->track.bc, MATROSKA_ID_AUDIOSAMPLINGFREQ, track->sample_rate);2709 put_ebml_float(mkv->track.bc, MATROSKA_ID_AUDIOSAMPLINGFREQ, track->sample_rate);
2667 put_ebml_float(mkv->track.bc, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate);2710 put_ebml_float(mkv->track.bc, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate);
@@ -2678,9 +2721,10 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) · 10 unmodified lines
2678 pkt->stream_index);2721 pkt->stream_index);
2679 return AVERROR(EINVAL);2722 return AVERROR(EINVAL);
2680 }2723 }
2681 avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET);2724 ret = mkv_update_codecprivate(s, mkv, side_data, side_data_size,
2682 mkv_write_codecprivate(s, mkv, par, side_data, side_data_size,2725 par, mkv->track.bc, track);
2683 1, 0, mkv->track.bc);2726 if (ret < 0)
2727 return ret;
2684 }2728 }
2685 break;2729 break;
2686#endif2730#endif
tests/ref/fate/aac-autobsf-adtstoasc+2−2
@@ -1,5 +1,5 @@
129daa1e1985dac4baae0774a0b56149d *tests/data/fate/aac-autobsf-adtstoasc.matroska14342e4f3f93b16514bda511b3b7fd93a *tests/data/fate/aac-autobsf-adtstoasc.matroska
26644 tests/data/fate/aac-autobsf-adtstoasc.matroska26642 tests/data/fate/aac-autobsf-adtstoasc.matroska
3#extradata 0: 2, 0x0030001c3#extradata 0: 2, 0x0030001c
4#tb 0: 1/10004#tb 0: 1/1000
5#media_type 0: audio5#media_type 0: audio

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t