X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=libhb%2Fstream.c;h=24093e62a74d7bd072e99782454323683c70b007;hb=4f0019f03c2e85e8634150ff0c9a31bee6d35ce5;hp=caed365cd2c73c03c9446469cfe8f24964adb39f;hpb=d8a53b1c4d411c318ab2215b8b2888c20d59218a;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/stream.c b/libhb/stream.c index caed365c..24093e62 100644 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -2831,6 +2831,175 @@ static void add_ffmpeg_audio( hb_title_t *title, hb_stream_t *stream, int id ) } } +/* + * Format: + * MkvVobSubtitlePrivateData = ( Line )* + * Line = FieldName ':' ' ' FieldValue '\n' + * FieldName = [^:]+ + * FieldValue = [^\n]+ + * + * The line of interest is: + * PaletteLine = "palette" ':' ' ' RRGGBB ( ',' ' ' RRGGBB )* + * + * More information on the format at: + * http://www.matroska.org/technical/specs/subtitles/images.html + */ +static int ffmpeg_parse_vobsub_extradata_mkv( AVCodecContext *codec, hb_subtitle_t *subtitle ) +{ + // lines = (string) codec->extradata; + char *lines = malloc( codec->extradata_size + 1 ); + if ( lines == NULL ) + return 1; + memcpy( lines, codec->extradata, codec->extradata_size ); + lines[codec->extradata_size] = '\0'; + + uint32_t rgb[16]; + int gotPalette = 0; + int gotDimensions = 0; + + char *curLine, *curLine_parserData; + for ( curLine = strtok_r( lines, "\n", &curLine_parserData ); + curLine; + curLine = strtok_r( NULL, "\n", &curLine_parserData ) ) + { + if (!gotPalette) + { + int numElementsRead = sscanf(curLine, "palette: " + "%06x, %06x, %06x, %06x, " + "%06x, %06x, %06x, %06x, " + "%06x, %06x, %06x, %06x, " + "%06x, %06x, %06x, %06x", + &rgb[0], &rgb[1], &rgb[2], &rgb[3], + &rgb[4], &rgb[5], &rgb[6], &rgb[7], + &rgb[8], &rgb[9], &rgb[10], &rgb[11], + &rgb[12], &rgb[13], &rgb[14], &rgb[15]); + + if (numElementsRead == 16) { + gotPalette = 1; + } + } + if (!gotDimensions) + { + int numElementsRead = sscanf(curLine, "size: %dx%d", + &subtitle->width, &subtitle->height); + + if (numElementsRead == 2) { + gotDimensions = 1; + } + } + if (gotPalette && gotDimensions) + break; + } + + if (subtitle->width == 0 || subtitle->height == 0) + { + subtitle->width = 720; + subtitle->height = 480; + } + + free( lines ); + + if ( gotPalette ) + { + int i; + for (i=0; i<16; i++) + subtitle->palette[i] = hb_rgb2yuv(rgb[i]); + return 0; + } + else + { + return 1; + } +} + +/* + * Format: 8-bit {0,Y,Cb,Cr} x 16 + */ +static int ffmpeg_parse_vobsub_extradata_mp4( AVCodecContext *codec, hb_subtitle_t *subtitle ) +{ + if ( codec->extradata_size != 4*16 ) + return 1; + + int i, j; + for ( i=0, j=0; i<16; i++, j+=4 ) + { + subtitle->palette[i] = + codec->extradata[j+1] << 16 | // Y + codec->extradata[j+2] << 8 | // Cb + codec->extradata[j+3] << 0; // Cr + } + if (codec->width <= 0 || codec->height <= 0) + { + subtitle->width = 720; + subtitle->height = 480; + } + else + { + subtitle->width = codec->width; + subtitle->height = codec->height; + } + return 0; +} + +/* + * Parses the 'subtitle->palette' information from the specific VOB subtitle track's private data. + * Returns 0 if successful or 1 if parsing failed or was incomplete. + */ +static int ffmpeg_parse_vobsub_extradata( AVCodecContext *codec, hb_subtitle_t *subtitle ) +{ + // XXX: Better if we actually chose the correct parser based on the input container + return + ffmpeg_parse_vobsub_extradata_mkv( codec, subtitle ) && + ffmpeg_parse_vobsub_extradata_mp4( codec, subtitle ); +} + +static void add_ffmpeg_subtitle( hb_title_t *title, hb_stream_t *stream, int id ) +{ + AVStream *st = stream->ffmpeg_ic->streams[id]; + AVCodecContext *codec = st->codec; + + hb_subtitle_t *subtitle = calloc( 1, sizeof(*subtitle) ); + + subtitle->id = id; + + switch ( codec->codec_id ) + { + case CODEC_ID_DVD_SUBTITLE: + subtitle->format = PICTURESUB; + subtitle->source = VOBSUB; + subtitle->config.dest = RENDERSUB; // By default render (burn-in) the VOBSUB. + if ( ffmpeg_parse_vobsub_extradata( codec, subtitle ) ) + hb_log( "add_ffmpeg_subtitle: malformed extradata for VOB subtitle track; " + "subtitle colors likely to be wrong" ); + break; + case CODEC_ID_TEXT: + subtitle->format = TEXTSUB; + subtitle->source = UTF8SUB; + subtitle->config.dest = PASSTHRUSUB; + break; + case CODEC_ID_MOV_TEXT: // TX3G + subtitle->format = TEXTSUB; + subtitle->source = TX3GSUB; + subtitle->config.dest = PASSTHRUSUB; + break; + case CODEC_ID_SSA: + subtitle->format = TEXTSUB; + subtitle->source = SSASUB; + subtitle->config.dest = PASSTHRUSUB; + break; + default: + hb_log( "add_ffmpeg_subtitle: unknown subtitle stream type: 0x%x", (int) codec->codec_id ); + free(subtitle); + return; + } + + iso639_lang_t *language = lang_for_code2( st->language ); + strcpy( subtitle->lang, language->eng_name ); + strncpy( subtitle->iso639_2, language->iso639_2, 4 ); + + hb_list_add(title->list_subtitle, subtitle); +} + static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream ) { AVFormatContext *ic = stream->ffmpeg_ic; @@ -2887,6 +3056,10 @@ static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream ) { add_ffmpeg_audio( title, stream, i ); } + else if ( ic->streams[i]->codec->codec_type == CODEC_TYPE_SUBTITLE ) + { + add_ffmpeg_subtitle( title, stream, i ); + } } title->container_name = strdup( ic->iformat->name ); @@ -3074,6 +3247,34 @@ static int ffmpeg_read( hb_stream_t *stream, hb_buffer_t *buf ) { buf->renderOffset = buf->start; } + + /* + * Fill out buf->stop for subtitle packets + * + * libavcodec's MKV demuxer stores the duration of UTF-8 subtitles (CODEC_ID_TEXT) + * in the 'convergence_duration' field for some reason. + * + * Other subtitles' durations are stored in the 'duration' field. + * + * VOB subtitles (CODEC_ID_DVD_SUBTITLE) do not have their duration stored in + * either field. This is not a problem because the VOB decoder can extract this + * information from the packet payload itself. + * + * SSA subtitles (CODEC_ID_SSA) do not have their duration stored in + * either field. This is not a problem because the SSA decoder can extract this + * information from the packet payload itself. + */ + enum CodecID ffmpeg_pkt_codec = stream->ffmpeg_ic->streams[stream->ffmpeg_pkt->stream_index]->codec->codec_id; + if ( ffmpeg_pkt_codec == CODEC_ID_TEXT ) { + int64_t ffmpeg_pkt_duration = stream->ffmpeg_pkt->convergence_duration; + int64_t buf_duration = av_to_hb_pts( ffmpeg_pkt_duration, tsconv ); + buf->stop = buf->start + buf_duration; + } + if ( ffmpeg_pkt_codec == CODEC_ID_MOV_TEXT ) { + int64_t ffmpeg_pkt_duration = stream->ffmpeg_pkt->duration; + int64_t buf_duration = av_to_hb_pts( ffmpeg_pkt_duration, tsconv ); + buf->stop = buf->start + buf_duration; + } /* * Check to see whether this video buffer is on a chapter