bluray.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * BluRay (libbluray) protocol
  3. *
  4. * Copyright (c) 2012 Petri Hintukainen <phintuka <at> users.sourceforge.net>
  5. *
  6. * This file is part of FFmpeg.
  7. *
  8. * FFmpeg is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * FFmpeg is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with FFmpeg; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #include <libbluray/bluray.h>
  23. #include "libavutil/avstring.h"
  24. #include "libavformat/avformat.h"
  25. #include "libavformat/url.h"
  26. #include "libavutil/opt.h"
  27. #define BLURAY_PROTO_PREFIX "bluray:"
  28. #define MIN_PLAYLIST_LENGTH 180 /* 3 min */
  29. typedef struct {
  30. const AVClass *class;
  31. BLURAY *bd;
  32. int playlist;
  33. int angle;
  34. int chapter;
  35. /*int region;*/
  36. } BlurayContext;
  37. #define OFFSET(x) offsetof(BlurayContext, x)
  38. static const AVOption options[] = {
  39. {"playlist", "", OFFSET(playlist), AV_OPT_TYPE_INT, { .i64=-1 }, -1, 99999, AV_OPT_FLAG_DECODING_PARAM },
  40. {"angle", "", OFFSET(angle), AV_OPT_TYPE_INT, { .i64=0 }, 0, 0xfe, AV_OPT_FLAG_DECODING_PARAM },
  41. {"chapter", "", OFFSET(chapter), AV_OPT_TYPE_INT, { .i64=1 }, 1, 0xfffe, AV_OPT_FLAG_DECODING_PARAM },
  42. /*{"region", "bluray player region code (1 = region A, 2 = region B, 4 = region C)", OFFSET(region), AV_OPT_TYPE_INT, { .i64=0 }, 0, 3, AV_OPT_FLAG_DECODING_PARAM },*/
  43. {NULL}
  44. };
  45. static const AVClass bluray_context_class = {
  46. .class_name = "bluray",
  47. .item_name = av_default_item_name,
  48. .option = options,
  49. .version = LIBAVUTIL_VERSION_INT,
  50. };
  51. static int check_disc_info(URLContext *h)
  52. {
  53. BlurayContext *bd = h->priv_data;
  54. const BLURAY_DISC_INFO *disc_info;
  55. disc_info = bd_get_disc_info(bd->bd);
  56. if (!disc_info) {
  57. av_log(h, AV_LOG_ERROR, "bd_get_disc_info() failed\n");
  58. return -1;
  59. }
  60. if (!disc_info->bluray_detected) {
  61. av_log(h, AV_LOG_ERROR, "BluRay disc not detected\n");
  62. return -1;
  63. }
  64. /* AACS */
  65. if (disc_info->aacs_detected && !disc_info->aacs_handled) {
  66. if (!disc_info->libaacs_detected) {
  67. av_log(h, AV_LOG_ERROR,
  68. "Media stream encrypted with AACS, install and configure libaacs\n");
  69. } else {
  70. av_log(h, AV_LOG_ERROR, "Your libaacs can't decrypt this media\n");
  71. }
  72. return -1;
  73. }
  74. /* BD+ */
  75. if (disc_info->bdplus_detected && !disc_info->bdplus_handled) {
  76. /*
  77. if (!disc_info->libbdplus_detected) {
  78. av_log(h, AV_LOG_ERROR,
  79. "Media stream encrypted with BD+, install and configure libbdplus");
  80. } else {
  81. */
  82. av_log(h, AV_LOG_ERROR, "Unable to decrypt BD+ encrypted media\n");
  83. /*}*/
  84. return -1;
  85. }
  86. return 0;
  87. }
  88. static int bluray_close(URLContext *h)
  89. {
  90. BlurayContext *bd = h->priv_data;
  91. if (bd->bd) {
  92. bd_close(bd->bd);
  93. }
  94. return 0;
  95. }
  96. static int bluray_open(URLContext *h, const char *path, int flags)
  97. {
  98. BlurayContext *bd = h->priv_data;
  99. int num_title_idx;
  100. const char *diskname = path;
  101. av_strstart(path, BLURAY_PROTO_PREFIX, &diskname);
  102. bd->bd = bd_open(diskname, NULL);
  103. if (!bd->bd) {
  104. av_log(h, AV_LOG_ERROR, "bd_open() failed\n");
  105. return AVERROR(EIO);
  106. }
  107. /* check if disc can be played */
  108. if (check_disc_info(h) < 0) {
  109. return AVERROR(EIO);
  110. }
  111. /* setup player registers */
  112. /* region code has no effect without menus
  113. if (bd->region > 0 && bd->region < 5) {
  114. av_log(h, AV_LOG_INFO, "setting region code to %d (%c)\n", bd->region, 'A' + (bd->region - 1));
  115. bd_set_player_setting(bd->bd, BLURAY_PLAYER_SETTING_REGION_CODE, bd->region);
  116. }
  117. */
  118. /* load title list */
  119. num_title_idx = bd_get_titles(bd->bd, TITLES_RELEVANT, MIN_PLAYLIST_LENGTH);
  120. av_log(h, AV_LOG_INFO, "%d usable playlists:\n", num_title_idx);
  121. if (num_title_idx < 1) {
  122. return AVERROR(EIO);
  123. }
  124. /* if playlist was not given, select longest playlist */
  125. if (bd->playlist < 0) {
  126. uint64_t duration = 0;
  127. int i;
  128. for (i = 0; i < num_title_idx; i++) {
  129. BLURAY_TITLE_INFO *info = bd_get_title_info(bd->bd, i, 0);
  130. av_log(h, AV_LOG_INFO, "playlist %05d.mpls (%d:%02d:%02d)\n",
  131. info->playlist,
  132. ((int)(info->duration / 90000) / 3600),
  133. ((int)(info->duration / 90000) % 3600) / 60,
  134. ((int)(info->duration / 90000) % 60));
  135. if (info->duration > duration) {
  136. bd->playlist = info->playlist;
  137. duration = info->duration;
  138. }
  139. bd_free_title_info(info);
  140. }
  141. av_log(h, AV_LOG_INFO, "selected %05d.mpls\n", bd->playlist);
  142. }
  143. /* select playlist */
  144. if (bd_select_playlist(bd->bd, bd->playlist) <= 0) {
  145. av_log(h, AV_LOG_ERROR, "bd_select_playlist(%05d.mpls) failed\n", bd->playlist);
  146. return AVERROR(EIO);
  147. }
  148. /* select angle */
  149. if (bd->angle >= 0) {
  150. bd_select_angle(bd->bd, bd->angle);
  151. }
  152. /* select chapter */
  153. if (bd->chapter > 1) {
  154. bd_seek_chapter(bd->bd, bd->chapter - 1);
  155. }
  156. return 0;
  157. }
  158. static int bluray_read(URLContext *h, unsigned char *buf, int size)
  159. {
  160. BlurayContext *bd = h->priv_data;
  161. int len;
  162. if (!bd || !bd->bd) {
  163. return AVERROR(EFAULT);
  164. }
  165. len = bd_read(bd->bd, buf, size);
  166. return len;
  167. }
  168. static int64_t bluray_seek(URLContext *h, int64_t pos, int whence)
  169. {
  170. BlurayContext *bd = h->priv_data;
  171. if (!bd || !bd->bd) {
  172. return AVERROR(EFAULT);
  173. }
  174. switch (whence) {
  175. case SEEK_SET:
  176. case SEEK_CUR:
  177. case SEEK_END:
  178. return bd_seek(bd->bd, pos);
  179. case AVSEEK_SIZE:
  180. return bd_get_title_size(bd->bd);
  181. }
  182. av_log(h, AV_LOG_ERROR, "Unsupported whence operation %d\n", whence);
  183. return AVERROR(EINVAL);
  184. }
  185. URLProtocol ff_bluray_protocol = {
  186. .name = "bluray",
  187. .url_close = bluray_close,
  188. .url_open = bluray_open,
  189. .url_read = bluray_read,
  190. .url_seek = bluray_seek,
  191. .priv_data_size = sizeof(BlurayContext),
  192. .priv_data_class = &bluray_context_class,
  193. };