bluray.c
Go to the documentation of this file.
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 
23 #include <libbluray/bluray.h>
24 
25 #include "libavutil/avstring.h"
26 #include "libavformat/avformat.h"
27 #include "libavformat/url.h"
28 #include "libavutil/opt.h"
29 
30 #define BLURAY_PROTO_PREFIX "bluray:"
31 #define MIN_PLAYLIST_LENGTH 180 /* 3 min */
32 
33 typedef struct {
34  const AVClass *class;
35 
36  BLURAY *bd;
37 
38  int playlist;
39  int angle;
40  int chapter;
41  /*int region;*/
43 
44 #define OFFSET(x) offsetof(BlurayContext, x)
45 static const AVOption options[] = {
46 {"playlist", "", OFFSET(playlist), AV_OPT_TYPE_INT, { .i64=-1 }, -1, 99999, AV_OPT_FLAG_DECODING_PARAM },
47 {"angle", "", OFFSET(angle), AV_OPT_TYPE_INT, { .i64=0 }, 0, 0xfe, AV_OPT_FLAG_DECODING_PARAM },
48 {"chapter", "", OFFSET(chapter), AV_OPT_TYPE_INT, { .i64=1 }, 1, 0xfffe, AV_OPT_FLAG_DECODING_PARAM },
49 /*{"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 },*/
50 {NULL}
51 };
52 
53 static const AVClass bluray_context_class = {
54  .class_name = "bluray",
55  .item_name = av_default_item_name,
56  .option = options,
57  .version = LIBAVUTIL_VERSION_INT,
58 };
59 
60 
62 {
63  BlurayContext *bd = h->priv_data;
64  const BLURAY_DISC_INFO *disc_info;
65 
66  disc_info = bd_get_disc_info(bd->bd);
67  if (!disc_info) {
68  av_log(h, AV_LOG_ERROR, "bd_get_disc_info() failed\n");
69  return -1;
70  }
71 
72  if (!disc_info->bluray_detected) {
73  av_log(h, AV_LOG_ERROR, "BluRay disc not detected\n");
74  return -1;
75  }
76 
77  /* AACS */
78  if (disc_info->aacs_detected && !disc_info->aacs_handled) {
79  if (!disc_info->libaacs_detected) {
81  "Media stream encrypted with AACS, install and configure libaacs\n");
82  } else {
83  av_log(h, AV_LOG_ERROR, "Your libaacs can't decrypt this media\n");
84  }
85  return -1;
86  }
87 
88  /* BD+ */
89  if (disc_info->bdplus_detected && !disc_info->bdplus_handled) {
90  /*
91  if (!disc_info->libbdplus_detected) {
92  av_log(h, AV_LOG_ERROR,
93  "Media stream encrypted with BD+, install and configure libbdplus");
94  } else {
95  */
96  av_log(h, AV_LOG_ERROR, "Unable to decrypt BD+ encrypted media\n");
97  /*}*/
98  return -1;
99  }
100 
101  return 0;
102 }
103 
104 static int bluray_close(URLContext *h)
105 {
106  BlurayContext *bd = h->priv_data;
107  if (bd->bd) {
108  bd_close(bd->bd);
109  }
110 
111  return 0;
112 }
113 
114 static int bluray_open(URLContext *h, const char *path, int flags)
115 {
116  BlurayContext *bd = h->priv_data;
117  int num_title_idx;
118  const char *diskname = path;
119 
120  av_strstart(path, BLURAY_PROTO_PREFIX, &diskname);
121 
122  bd->bd = bd_open(diskname, NULL);
123  if (!bd->bd) {
124  av_log(h, AV_LOG_ERROR, "bd_open() failed\n");
125  return AVERROR(EIO);
126  }
127 
128  /* check if disc can be played */
129  if (check_disc_info(h) < 0) {
130  return AVERROR(EIO);
131  }
132 
133  /* setup player registers */
134  /* region code has no effect without menus
135  if (bd->region > 0 && bd->region < 5) {
136  av_log(h, AV_LOG_INFO, "setting region code to %d (%c)\n", bd->region, 'A' + (bd->region - 1));
137  bd_set_player_setting(bd->bd, BLURAY_PLAYER_SETTING_REGION_CODE, bd->region);
138  }
139  */
140 
141  /* load title list */
142  num_title_idx = bd_get_titles(bd->bd, TITLES_RELEVANT, MIN_PLAYLIST_LENGTH);
143  av_log(h, AV_LOG_INFO, "%d usable playlists:\n", num_title_idx);
144  if (num_title_idx < 1) {
145  return AVERROR(EIO);
146  }
147 
148  /* if playlist was not given, select longest playlist */
149  if (bd->playlist < 0) {
150  uint64_t duration = 0;
151  int i;
152  for (i = 0; i < num_title_idx; i++) {
153  BLURAY_TITLE_INFO *info = bd_get_title_info(bd->bd, i, 0);
154 
155  av_log(h, AV_LOG_INFO, "playlist %05d.mpls (%d:%02d:%02d)\n",
156  info->playlist,
157  ((int)(info->duration / 90000) / 3600),
158  ((int)(info->duration / 90000) % 3600) / 60,
159  ((int)(info->duration / 90000) % 60));
160 
161  if (info->duration > duration) {
162  bd->playlist = info->playlist;
163  duration = info->duration;
164  }
165 
166  bd_free_title_info(info);
167  }
168  av_log(h, AV_LOG_INFO, "selected %05d.mpls\n", bd->playlist);
169  }
170 
171  /* select playlist */
172  if (bd_select_playlist(bd->bd, bd->playlist) <= 0) {
173  av_log(h, AV_LOG_ERROR, "bd_select_playlist(%05d.mpls) failed\n", bd->playlist);
174  return AVERROR(EIO);
175  }
176 
177  /* select angle */
178  if (bd->angle >= 0) {
179  bd_select_angle(bd->bd, bd->angle);
180  }
181 
182  /* select chapter */
183  if (bd->chapter > 1) {
184  bd_seek_chapter(bd->bd, bd->chapter - 1);
185  }
186 
187  return 0;
188 }
189 
190 static int bluray_read(URLContext *h, unsigned char *buf, int size)
191 {
192  BlurayContext *bd = h->priv_data;
193  int len;
194 
195  if (!bd || !bd->bd) {
196  return AVERROR(EFAULT);
197  }
198 
199  len = bd_read(bd->bd, buf, size);
200 
201  return len;
202 }
203 
204 static int64_t bluray_seek(URLContext *h, int64_t pos, int whence)
205 {
206  BlurayContext *bd = h->priv_data;
207 
208  if (!bd || !bd->bd) {
209  return AVERROR(EFAULT);
210  }
211 
212  switch (whence) {
213  case SEEK_SET:
214  case SEEK_CUR:
215  case SEEK_END:
216  return bd_seek(bd->bd, pos);
217 
218  case AVSEEK_SIZE:
219  return bd_get_title_size(bd->bd);
220  }
221 
222  av_log(h, AV_LOG_ERROR, "Unsupported whence operation %d\n", whence);
223  return AVERROR(EINVAL);
224 }
225 
226 
228  .name = "bluray",
229  .url_close = bluray_close,
230  .url_open = bluray_open,
231  .url_read = bluray_read,
232  .url_seek = bluray_seek,
233  .priv_data_size = sizeof(BlurayContext),
234  .priv_data_class = &bluray_context_class,
235 };
#define OFFSET(x)
Definition: bluray.c:44
AVOption.
Definition: opt.h:251
av_default_item_name
static int bluray_open(URLContext *h, const char *path, int flags)
Definition: bluray.c:114
BLURAY * bd
Definition: bluray.c:36
static const AVClass bluray_context_class
Definition: bluray.c:53
int chapter
Definition: bluray.c:40
static int check_disc_info(URLContext *h)
Definition: bluray.c:61
#define MIN_PLAYLIST_LENGTH
Definition: bluray.c:31
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:55
AVOptions.
int playlist
Definition: bluray.c:38
static int64_t duration
Definition: ffplay.c:294
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
URLProtocol ff_bluray_protocol
Definition: bluray.c:227
int size
MIPS optimizations info
Definition: mips.txt:2
static int bluray_read(URLContext *h, unsigned char *buf, int size)
Definition: bluray.c:190
int angle
Definition: bluray.c:39
LIBAVUTIL_VERSION_INT
Definition: eval.c:55
NULL
Definition: eval.c:55
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
Definition: url.h:41
Describe the class of an AVClass context structure.
Definition: log.h:50
synthesis window for stochastic i
void * priv_data
Definition: url.h:44
#define AV_OPT_FLAG_DECODING_PARAM
a generic parameter which can be set by the user for demuxing or decoding
Definition: opt.h:282
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
const char * name
Definition: url.h:55
static int flags
Definition: cpu.c:23
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:33
Main libavformat public API header.
#define BLURAY_PROTO_PREFIX
Definition: bluray.c:30
#define AVSEEK_SIZE
Passing this as the "whence" parameter to a seek function causes it to return the filesize without se...
Definition: avio.h:222
int len
static int bluray_close(URLContext *h)
Definition: bluray.c:104
#define AV_LOG_INFO
Definition: log.h:156
unbuffered private I/O API
static const AVOption options[]
Definition: bluray.c:45
static int64_t bluray_seek(URLContext *h, int64_t pos, int whence)
Definition: bluray.c:204