You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

370 lines
10KB

  1. /*
  2. * This file is part of FFmpeg.
  3. *
  4. * FFmpeg is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * FFmpeg is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with FFmpeg; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "cbs.h"
  19. #include "cbs_internal.h"
  20. #include "cbs_h264.h"
  21. #include "cbs_h265.h"
  22. #include "cbs_sei.h"
  23. static void cbs_free_user_data_registered(void *opaque, uint8_t *data)
  24. {
  25. SEIRawUserDataRegistered *udr = (SEIRawUserDataRegistered*)data;
  26. av_buffer_unref(&udr->data_ref);
  27. av_free(udr);
  28. }
  29. static void cbs_free_user_data_unregistered(void *opaque, uint8_t *data)
  30. {
  31. SEIRawUserDataUnregistered *udu = (SEIRawUserDataUnregistered*)data;
  32. av_buffer_unref(&udu->data_ref);
  33. av_free(udu);
  34. }
  35. int ff_cbs_sei_alloc_message_payload(SEIRawMessage *message,
  36. const SEIMessageTypeDescriptor *desc)
  37. {
  38. void (*free_func)(void*, uint8_t*);
  39. av_assert0(message->payload == NULL &&
  40. message->payload_ref == NULL);
  41. message->payload_type = desc->type;
  42. if (desc->type == SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35)
  43. free_func = &cbs_free_user_data_registered;
  44. else if (desc->type == SEI_TYPE_USER_DATA_UNREGISTERED)
  45. free_func = &cbs_free_user_data_unregistered;
  46. else
  47. free_func = NULL;
  48. if (free_func) {
  49. message->payload = av_mallocz(desc->size);
  50. if (!message->payload)
  51. return AVERROR(ENOMEM);
  52. message->payload_ref =
  53. av_buffer_create(message->payload, desc->size,
  54. free_func, NULL, 0);
  55. } else {
  56. message->payload_ref = av_buffer_alloc(desc->size);
  57. }
  58. if (!message->payload_ref) {
  59. av_freep(&message->payload);
  60. return AVERROR(ENOMEM);
  61. }
  62. message->payload = message->payload_ref->data;
  63. return 0;
  64. }
  65. int ff_cbs_sei_list_add(SEIRawMessageList *list)
  66. {
  67. void *ptr;
  68. int old_count = list->nb_messages_allocated;
  69. av_assert0(list->nb_messages <= old_count);
  70. if (list->nb_messages + 1 > old_count) {
  71. int new_count = 2 * old_count + 1;
  72. ptr = av_realloc_array(list->messages,
  73. new_count, sizeof(*list->messages));
  74. if (!ptr)
  75. return AVERROR(ENOMEM);
  76. list->messages = ptr;
  77. list->nb_messages_allocated = new_count;
  78. // Zero the newly-added entries.
  79. memset(list->messages + old_count, 0,
  80. (new_count - old_count) * sizeof(*list->messages));
  81. }
  82. ++list->nb_messages;
  83. return 0;
  84. }
  85. void ff_cbs_sei_free_message_list(SEIRawMessageList *list)
  86. {
  87. for (int i = 0; i < list->nb_messages; i++) {
  88. SEIRawMessage *message = &list->messages[i];
  89. av_buffer_unref(&message->payload_ref);
  90. av_buffer_unref(&message->extension_data_ref);
  91. }
  92. av_free(list->messages);
  93. }
  94. static int cbs_sei_get_unit(CodedBitstreamContext *ctx,
  95. CodedBitstreamFragment *au,
  96. int prefix,
  97. CodedBitstreamUnit **sei_unit)
  98. {
  99. CodedBitstreamUnit *unit;
  100. int sei_type, highest_vcl_type, err, i, position;
  101. switch (ctx->codec->codec_id) {
  102. case AV_CODEC_ID_H264:
  103. // (We can ignore auxiliary slices because we only have prefix
  104. // SEI in H.264 and an auxiliary picture must always follow a
  105. // primary picture.)
  106. highest_vcl_type = H264_NAL_IDR_SLICE;
  107. if (prefix)
  108. sei_type = H264_NAL_SEI;
  109. else
  110. return AVERROR(EINVAL);
  111. break;
  112. case AV_CODEC_ID_H265:
  113. highest_vcl_type = HEVC_NAL_RSV_VCL31;
  114. if (prefix)
  115. sei_type = HEVC_NAL_SEI_PREFIX;
  116. else
  117. sei_type = HEVC_NAL_SEI_SUFFIX;
  118. break;
  119. default:
  120. return AVERROR(EINVAL);
  121. }
  122. // Find an existing SEI NAL unit of the right type.
  123. unit = NULL;
  124. for (i = 0; i < au->nb_units; i++) {
  125. if (au->units[i].type == sei_type) {
  126. unit = &au->units[i];
  127. break;
  128. }
  129. }
  130. if (unit) {
  131. *sei_unit = unit;
  132. return 0;
  133. }
  134. // Need to add a new SEI NAL unit ...
  135. if (prefix) {
  136. // ... before the first VCL NAL unit.
  137. for (i = 0; i < au->nb_units; i++) {
  138. if (au->units[i].type < highest_vcl_type)
  139. break;
  140. }
  141. position = i;
  142. } else {
  143. // ... after the last VCL NAL unit.
  144. for (i = au->nb_units - 1; i >= 0; i--) {
  145. if (au->units[i].type < highest_vcl_type)
  146. break;
  147. }
  148. if (i < 0) {
  149. // No VCL units; just put it at the end.
  150. position = -1;
  151. } else {
  152. position = i + 1;
  153. }
  154. }
  155. err = ff_cbs_insert_unit_content(au, position, sei_type,
  156. NULL, NULL);
  157. if (err < 0)
  158. return err;
  159. unit = &au->units[position];
  160. unit->type = sei_type;
  161. err = ff_cbs_alloc_unit_content2(ctx, unit);
  162. if (err < 0)
  163. return err;
  164. switch (ctx->codec->codec_id) {
  165. case AV_CODEC_ID_H264:
  166. {
  167. H264RawSEI sei = {
  168. .nal_unit_header = {
  169. .nal_ref_idc = 0,
  170. .nal_unit_type = sei_type,
  171. },
  172. };
  173. memcpy(unit->content, &sei, sizeof(sei));
  174. }
  175. break;
  176. case AV_CODEC_ID_H265:
  177. {
  178. H265RawSEI sei = {
  179. .nal_unit_header = {
  180. .nal_unit_type = sei_type,
  181. .nuh_layer_id = 0,
  182. .nuh_temporal_id_plus1 = 1,
  183. },
  184. };
  185. memcpy(unit->content, &sei, sizeof(sei));
  186. }
  187. break;
  188. default:
  189. av_assert0(0);
  190. }
  191. *sei_unit = unit;
  192. return 0;
  193. }
  194. static int cbs_sei_get_message_list(CodedBitstreamContext *ctx,
  195. CodedBitstreamUnit *unit,
  196. SEIRawMessageList **list)
  197. {
  198. switch (ctx->codec->codec_id) {
  199. case AV_CODEC_ID_H264:
  200. {
  201. H264RawSEI *sei = unit->content;
  202. if (unit->type != H264_NAL_SEI)
  203. return AVERROR(EINVAL);
  204. *list = &sei->message_list;
  205. }
  206. break;
  207. case AV_CODEC_ID_H265:
  208. {
  209. H265RawSEI *sei = unit->content;
  210. if (unit->type != HEVC_NAL_SEI_PREFIX &&
  211. unit->type != HEVC_NAL_SEI_SUFFIX)
  212. return AVERROR(EINVAL);
  213. *list = &sei->message_list;
  214. }
  215. break;
  216. default:
  217. return AVERROR(EINVAL);
  218. }
  219. return 0;
  220. }
  221. int ff_cbs_sei_add_message(CodedBitstreamContext *ctx,
  222. CodedBitstreamFragment *au,
  223. int prefix,
  224. uint32_t payload_type,
  225. void *payload_data,
  226. AVBufferRef *payload_buf)
  227. {
  228. const SEIMessageTypeDescriptor *desc;
  229. CodedBitstreamUnit *unit;
  230. SEIRawMessageList *list;
  231. SEIRawMessage *message;
  232. AVBufferRef *payload_ref;
  233. int err;
  234. desc = ff_cbs_sei_find_type(ctx, payload_type);
  235. if (!desc)
  236. return AVERROR(EINVAL);
  237. if (payload_buf) {
  238. payload_ref = av_buffer_ref(payload_buf);
  239. if (!payload_ref)
  240. return AVERROR(ENOMEM);
  241. } else {
  242. payload_ref = NULL;
  243. }
  244. // Find an existing SEI unit or make a new one to add to.
  245. err = cbs_sei_get_unit(ctx, au, prefix, &unit);
  246. if (err < 0)
  247. return err;
  248. // Find the message list inside the codec-dependent unit.
  249. err = cbs_sei_get_message_list(ctx, unit, &list);
  250. if (err < 0)
  251. return err;
  252. // Add a new message to the message list.
  253. err = ff_cbs_sei_list_add(list);
  254. if (err < 0)
  255. return err;
  256. message = &list->messages[list->nb_messages - 1];
  257. message->payload_type = payload_type;
  258. message->payload = payload_data;
  259. message->payload_ref = payload_ref;
  260. return 0;
  261. }
  262. int ff_cbs_sei_find_message(CodedBitstreamContext *ctx,
  263. CodedBitstreamFragment *au,
  264. uint32_t payload_type,
  265. SEIRawMessage **iter)
  266. {
  267. int err, i, j, found;
  268. found = 0;
  269. for (i = 0; i < au->nb_units; i++) {
  270. CodedBitstreamUnit *unit = &au->units[i];
  271. SEIRawMessageList *list;
  272. err = cbs_sei_get_message_list(ctx, unit, &list);
  273. if (err < 0)
  274. continue;
  275. for (j = 0; j < list->nb_messages; j++) {
  276. SEIRawMessage *message = &list->messages[j];
  277. if (message->payload_type == payload_type) {
  278. if (!*iter || found) {
  279. *iter = message;
  280. return 0;
  281. }
  282. if (message == *iter)
  283. found = 1;
  284. }
  285. }
  286. }
  287. return AVERROR(ENOENT);
  288. }
  289. static void cbs_sei_delete_message(SEIRawMessageList *list,
  290. int position)
  291. {
  292. SEIRawMessage *message;
  293. av_assert0(0 <= position && position < list->nb_messages);
  294. message = &list->messages[position];
  295. av_buffer_unref(&message->payload_ref);
  296. av_buffer_unref(&message->extension_data_ref);
  297. --list->nb_messages;
  298. if (list->nb_messages > 0) {
  299. memmove(list->messages + position,
  300. list->messages + position + 1,
  301. (list->nb_messages - position) * sizeof(*list->messages));
  302. }
  303. }
  304. void ff_cbs_sei_delete_message_type(CodedBitstreamContext *ctx,
  305. CodedBitstreamFragment *au,
  306. uint32_t payload_type)
  307. {
  308. int err, i, j;
  309. for (i = 0; i < au->nb_units; i++) {
  310. CodedBitstreamUnit *unit = &au->units[i];
  311. SEIRawMessageList *list;
  312. err = cbs_sei_get_message_list(ctx, unit, &list);
  313. if (err < 0)
  314. continue;
  315. for (j = list->nb_messages - 1; j >= 0; j--) {
  316. if (list->messages[j].payload_type == payload_type)
  317. cbs_sei_delete_message(list, j);
  318. }
  319. }
  320. }