annotate ffmpeg/libavformat/bluray.c @ 13:844d341cf643 tip

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