fprintf(stderr,_("%s err: %s\n"),msg, errmsg);
}
-FFPacket::FFPacket()
-{
- init();
-}
-
-FFPacket::~FFPacket()
-{
- av_packet_unref(&pkt);
-}
-
void FFPacket::init()
{
av_init_packet(&pkt);
pkt.data = 0; pkt.size = 0;
}
+void FFPacket::finit()
+{
+ av_packet_unref(&pkt);
+}
FFrame::FFrame(FFStream *fst)
{
nudge = AV_NOPTS_VALUE;
seek_pos = curr_pos = 0;
seeked = 1; eof = 0;
- index_markers = 0;
reading = writing = 0;
flushed = 0;
need_packet = 1;
if( ret >= 0 )
reading = 1;
else
- eprintf("FFStream::decode_activate: open decoder failed\n");
+ eprintf(_("open decoder failed\n"));
}
else
- eprintf("FFStream::decode_activate: can't clone input file\n");
+ eprintf(_("can't clone input file\n"));
av_dict_free(&copts);
ff_unlock();
}
frame, AV_BUFFERSRC_FLAG_KEEP_REF);
if( ret < 0 ) {
av_frame_unref(frame);
- eprintf("FFStream::load_filter: av_buffersrc_add_frame_flags failed\n");
+ eprintf(_("av_buffersrc_add_frame_flags failed\n"));
}
return ret;
}
int FFStream::seek(int64_t no, double rate)
{
- if( no < 0 ) no = 0;
+ int64_t tstmp = -INT64_MAX+1;
// default ffmpeg native seek
int npkts = 1;
int64_t pos = no, plmt = -1;
+ IndexMarks *index_markers = get_markers();
if( index_markers && index_markers->size() > 1 ) {
IndexMarks &marks = *index_markers;
int i = marks.find(pos);
if( no-n < 30*rate ) {
if( n < 0 ) n = 0;
pos = n;
- if( ++i < marks.size() ) plmt = marks[i].pos;
+ if( i < marks.size() ) plmt = marks[i].pos;
npkts = MAX_RETRY;
}
}
- double secs = pos / rate;
- int64_t pkt_ts, tstmp = secs * st->time_base.den / st->time_base.num;
- if( nudge != AV_NOPTS_VALUE ) tstmp += nudge;
+ if( pos > 0 ) {
+ double secs = pos / rate;
+ tstmp = secs * st->time_base.den / st->time_base.num;
+ if( nudge != AV_NOPTS_VALUE ) tstmp += nudge;
+ }
int ret = avformat_seek_file(fmt_ctx, st->index,
-INT64_MAX, tstmp, INT64_MAX, AVSEEK_FLAG_ANY);
if( ret >= 0 ) {
avcodec_flush_buffers(st->codec);
+ ipkt.finit(); ipkt.init();
need_packet = 0; flushed = 0;
seeked = 1; st_eof(0);
// read up to retry packets, limited to npkts in stream, and not past pkt.pos plmt
- for( int retry=MAX_RETRY; ret>=0 && --retry>=0; ) {
+ for(;;) {
if( read_packet() <= 0 ) { ret = -1; break; }
if( plmt >= 0 && ipkt->pos >= plmt ) break;
if( ipkt->stream_index != st->index ) continue;
if( --npkts <= 0 ) break;
- if( (pkt_ts=ipkt->dts) == AV_NOPTS_VALUE &&
- (pkt_ts=ipkt->pts) == AV_NOPTS_VALUE ) continue;
+ int64_t pkt_ts = ipkt->dts != AV_NOPTS_VALUE ? ipkt->dts : ipkt->pts;
+ if( pkt_ts == AV_NOPTS_VALUE ) continue;
if( pkt_ts >= tstmp ) break;
}
}
{
IndexState *index_state = ffmpeg->file_base->asset->index_state;
if( !index_state || idx >= index_state->audio_markers.size() ) return;
+ if( index_state->marker_status == MARKERS_NOTTESTED ) return;
FFStream::load_markers(*index_state->audio_markers[idx], sample_rate);
}
+IndexMarks *FFAudioStream::get_markers()
+{
+ IndexState *index_state = ffmpeg->file_base->asset->index_state;
+ if( !index_state || idx >= index_state->audio_markers.size() ) return 0;
+ return index_state->audio_markers[idx];
+}
+
FFVideoStream::FFVideoStream(FFMPEG *ffmpeg, AVStream *strm, int idx, int fidx)
: FFStream(ffmpeg, strm, fidx)
{
case BC_RGBA8888: return AV_PIX_FMT_RGBA;
case BC_BGR8888: return AV_PIX_FMT_BGR0;
case BC_BGR888: return AV_PIX_FMT_BGR24;
+ case BC_ARGB8888: return AV_PIX_FMT_ARGB;
+ case BC_ABGR8888: return AV_PIX_FMT_ABGR;
+ case BC_RGB8: return AV_PIX_FMT_RGB8;
case BC_YUV420P: return AV_PIX_FMT_YUV420P;
case BC_YUV422P: return AV_PIX_FMT_YUV422P;
case BC_YUV444P: return AV_PIX_FMT_YUV444P;
case AV_PIX_FMT_RGBA: return BC_RGBA8888;
case AV_PIX_FMT_BGR0: return BC_BGR8888;
case AV_PIX_FMT_BGR24: return BC_BGR888;
+ case AV_PIX_FMT_ARGB: return BC_ARGB8888;
+ case AV_PIX_FMT_ABGR: return BC_ABGR8888;
+ case AV_PIX_FMT_RGB8: return BC_RGB8;
case AV_PIX_FMT_YUV420P: return BC_YUV420P;
case AV_PIX_FMT_YUV422P: return BC_YUV422P;
case AV_PIX_FMT_YUV444P: return BC_YUV444P;
default: break;
}
- return BC_TRANSPARENCY;
+ return -1;
}
int FFVideoConvert::convert_picture_vframe(VFrame *frame,
AVFrame *ip, AVPixelFormat ifmt, int iw, int ih)
{
+ // try bc_xfer methods
+ int imodel = pix_fmt_to_color_model(ifmt);
+ if( imodel >= 0 ) {
+ long y_ofs = 0, u_ofs = 0, v_ofs = 0;
+ uint8_t *data = ip->data[0];
+ if( BC_CModels::is_yuv(imodel) ) {
+ u_ofs = ip->data[1] - data;
+ v_ofs = ip->data[2] - data;
+ }
+ VFrame iframe(data, -1, y_ofs, u_ofs, v_ofs, iw, ih, imodel, ip->linesize[0]);
+ frame->transfer_from(&iframe);
+ return 0;
+ }
+ // try sws methods
AVFrame opic;
int cmodel = frame->get_color_model();
AVPixelFormat ofmt = color_model_to_pix_fmt(cmodel);
void FFVideoStream::load_markers()
{
IndexState *index_state = ffmpeg->file_base->asset->index_state;
- if( idx >= index_state->video_markers.size() ) return;
+ if( !index_state || idx >= index_state->video_markers.size() ) return;
FFStream::load_markers(*index_state->video_markers[idx], frame_rate);
}
+IndexMarks *FFVideoStream::get_markers()
+{
+ IndexState *index_state = ffmpeg->file_base->asset->index_state;
+ if( !index_state || idx >= index_state->video_markers.size() ) return 0;
+ return !index_state ? 0 : index_state->video_markers[idx];
+}
+
FFMPEG::FFMPEG(FileBase *file_base)
{
void FFMPEG::set_option_path(char *path, const char *fmt, ...)
{
- get_exe_path(path);
- strcat(path, "/ffmpeg/");
+ char *ep = path + BCTEXTLEN-1;
+ strncpy(path, File::get_cindat_path(), ep-path);
+ strncat(path, "/ffmpeg/", ep-path);
path += strlen(path);
va_list ap;
va_start(ap, fmt);
- vsprintf(path, fmt, ap);
+ path += vsnprintf(path, ep-path, fmt, ap);
va_end(ap);
+ *path = 0;
}
void FFMPEG::get_option_path(char *path, const char *type, const char *spec)
set_option_path(path, "%s/%s", type, spec);
}
-int FFMPEG::get_format(char *format, const char *path, char *spec)
+int FFMPEG::get_format(char *format, const char *path, const char *spec)
{
char option_path[BCTEXTLEN], line[BCTEXTLEN], codec[BCTEXTLEN];
get_option_path(option_path, path, spec);
return ret;
}
+int FFMPEG::get_codec(char *codec, const char *path, const char *spec)
+{
+ char option_path[BCTEXTLEN], line[BCTEXTLEN], format[BCTEXTLEN];
+ get_option_path(option_path, path, spec);
+ FILE *fp = fopen(option_path,"r");
+ if( !fp ) return 1;
+ int ret = 0;
+ if( !fgets(line, sizeof(line), fp) ) ret = 1;
+ fclose(fp);
+ if( !ret ) {
+ line[sizeof(line)-1] = 0;
+ ret = scan_option_line(line, format, codec);
+ }
+ if( !ret ) {
+ char *vp = codec, *ep = vp+BCTEXTLEN-1;
+ while( vp < ep && *vp && *vp != '|' ) ++vp;
+ if( *vp == '|' ) --vp;
+ while( vp > codec && (*vp==' ' || *vp=='\t') ) *vp-- = 0;
+ }
+ return ret;
+}
+
int FFMPEG::get_file_format()
{
int ret = 0;
{
if( asset->format != FILE_FFMPEG ) return;
strcpy(asset->fformat, text);
- strcpy(asset->ff_audio_options, "");
- strcpy(asset->ff_video_options, "");
- asset->audio_data = !load_defaults("audio", text, asset->acodec,
- asset->ff_audio_options, sizeof(asset->ff_audio_options));
- asset->video_data = !load_defaults("video", text, asset->vcodec,
- asset->ff_video_options, sizeof(asset->ff_video_options));
+ if( !asset->ff_audio_options[0] ) {
+ asset->audio_data = !load_defaults("audio", text, asset->acodec,
+ asset->ff_audio_options, sizeof(asset->ff_audio_options));
+ }
+ if( !asset->ff_video_options[0] ) {
+ asset->video_data = !load_defaults("video", text, asset->vcodec,
+ asset->ff_video_options, sizeof(asset->ff_video_options));
+ }
}
int FFMPEG::get_encoder(const char *options,
{
FILE *fp = fopen(options,"r");
if( !fp ) {
- eprintf("FFMPEG::get_encoder: options open failed %s\n",options);
+ eprintf(_("options open failed %s\n"),options);
return 1;
}
if( get_encoder(fp, format, codec, bsfilter, bsargs) )
- eprintf(_("FFMPEG::get_encoder:"
- " err: format/codec not found %s\n"), options);
+ eprintf(_("format/codec not found %s\n"), options);
fclose(fp);
return 0;
}
if( line[0] == '\n' ) continue;
char key[BCSTRLEN], val[BCTEXTLEN];
if( scan_option_line(line, key, val) ) {
- eprintf(_("FFMPEG::read_options:"
- " err reading %s: line %d\n"), options, no);
+ eprintf(_("err reading %s: line %d\n"), options, no);
ret = 1;
}
if( !ret ) {
{
struct stat st;
if( stat(fmt_ctx->filename, &st) < 0 ) {
- eprintf("FFMPEG::open_decoder: can't stat file: %s\n",
- fmt_ctx->filename);
+ eprintf(_("can't stat file: %s\n"), fmt_ctx->filename);
return 1;
}
int fd = ::open(filename,O_WRONLY);
if( fd < 0 ) fd = open(filename,O_WRONLY+O_CREAT,0666);
if( fd < 0 ) {
- eprintf("FFMPEG::init_encoder: bad file path: %s\n", filename);
+ eprintf(_("bad file path: %s\n"), filename);
return 1;
}
::close(fd);
int ret = get_file_format();
if( ret > 0 ) {
- eprintf("FFMPEG::init_encoder: bad file format: %s\n", filename);
+ eprintf(_("bad file format: %s\n"), filename);
return 1;
}
if( ret < 0 ) {
- eprintf("FFMPEG::init_encoder: mismatch audio/video file format: %s\n", filename);
+ eprintf(_("mismatch audio/video file format: %s\n"), filename);
return 1;
}
ff_lock("FFMPEG::init_encoder");
av_register_all();
avformat_alloc_output_context2(&fmt_ctx, 0, file_format, filename);
if( !fmt_ctx ) {
- eprintf("FFMPEG::init_encoder: failed: %s\n", filename);
+ eprintf(_("failed: %s\n"), filename);
ret = 1;
}
if( !ret ) {
char format_name[BCSTRLEN], codec_name[BCTEXTLEN];
char bsfilter[BCSTRLEN], bsargs[BCTEXTLEN];
if( get_encoder(option_path, format_name, codec_name, bsfilter, bsargs) ) {
- eprintf("FFMPEG::open_encoder: get_encoder failed %s:%s\n",
- option_path, filename);
+ eprintf(_("get_encoder failed %s:%s\n"), option_path, filename);
return 1;
}
const AVCodecDescriptor *codec_desc = 0;
AVCodec *codec = avcodec_find_encoder_by_name(codec_name);
if( !codec ) {
- eprintf("FFMPEG::open_encoder: cant find codec %s:%s\n",
- codec_name, filename);
+ eprintf(_("cant find codec %s:%s\n"), codec_name, filename);
ret = 1;
}
if( !ret ) {
codec_desc = avcodec_descriptor_get(codec->id);
if( !codec_desc ) {
- eprintf("FFMPEG::open_encoder: unknown codec %s:%s\n",
- codec_name, filename);
+ eprintf(_("unknown codec %s:%s\n"), codec_name, filename);
ret = 1;
}
}
if( !ret ) {
st = avformat_new_stream(fmt_ctx, 0);
if( !st ) {
- eprintf("FFMPEG::open_encoder: cant create stream %s:%s\n",
- codec_name, filename);
+ eprintf(_("cant create stream %s:%s\n"), codec_name, filename);
ret = 1;
}
}
switch( codec_desc->type ) {
case AVMEDIA_TYPE_AUDIO: {
if( has_audio ) {
- eprintf("FFMPEG::open_encoder: duplicate audio %s:%s\n",
- codec_name, filename);
+ eprintf(_("duplicate audio %s:%s\n"), codec_name, filename);
ret = 1;
break;
}
has_audio = 1;
if( scan_options(asset->ff_audio_options, sopts, st) ) {
- eprintf("FFMPEG::open_encoder: bad audio options %s:%s\n",
- codec_name, filename);
+ eprintf(_("bad audio options %s:%s\n"), codec_name, filename);
ret = 1;
break;
}
ctx->channel_layout = av_get_default_channel_layout(ctx->channels);
ctx->sample_rate = check_sample_rate(codec, asset->sample_rate);
if( !ctx->sample_rate ) {
- eprintf("FFMPEG::open_encoder:"
- " check_sample_rate failed %s\n", filename);
+ eprintf(_("check_sample_rate failed %s\n"), filename);
ret = 1;
break;
}
break; }
case AVMEDIA_TYPE_VIDEO: {
if( has_video ) {
- eprintf("FFMPEG::open_encoder: duplicate video %s:%s\n",
- codec_name, filename);
+ eprintf(_("duplicate video %s:%s\n"), codec_name, filename);
ret = 1;
break;
}
has_video = 1;
if( scan_options(asset->ff_video_options, sopts, st) ) {
- eprintf("FFMPEG::open_encoder: bad video options %s:%s\n",
- codec_name, filename);
+ eprintf(_("bad video options %s:%s\n"), codec_name, filename);
ret = 1;
break;
}
ctx->pix_fmt = codec->pix_fmts ? codec->pix_fmts[0] : AV_PIX_FMT_YUV420P;
AVRational frame_rate = check_frame_rate(codec, vid->frame_rate);
if( !frame_rate.num || !frame_rate.den ) {
- eprintf("FFMPEG::open_encoder:"
- " check_frame_rate failed %s\n", filename);
+ eprintf(_("check_frame_rate failed %s\n"), filename);
ret = 1;
break;
}
vid->writing = -1;
break; }
default:
- eprintf("FFMPEG::open_encoder: not audio/video, %s:%s\n",
- codec_name, filename);
+ eprintf(_("not audio/video, %s:%s\n"), codec_name, filename);
ret = 1;
}
}
ret = avcodec_open2(st->codec, codec, &sopts);
if( ret < 0 ) {
ff_err(ret,"FFMPEG::open_encoder");
- eprintf("FFMPEG::open_encoder: open failed %s:%s\n",
- codec_name, filename);
+ eprintf(_("open failed %s:%s\n"), codec_name, filename);
ret = 1;
}
else
if( running() ) {
done = 1;
mux_lock->unlock();
- join();
}
+ join();
}
void FFMPEG::flow_off()
AVStream *st = ffaudio[stream]->st;
AVCodecID id = st->codec->codec_id;
const AVCodecDescriptor *desc = avcodec_descriptor_get(id);
- return desc ? desc->name : "Unknown";
+ return desc ? desc->name : _("Unknown");
}
int FFMPEG::ff_audio_pid(int stream)
AVStream *st = ffvideo[stream]->st;
AVCodecID id = st->codec->codec_id;
const AVCodecDescriptor *desc = avcodec_descriptor_get(id);
- return desc ? desc->name : "Unknown";
+ return desc ? desc->name : _("Unknown");
}
double FFMPEG::ff_frame_rate(int stream)
av_init_packet(&pkt);
AVFrame *frame = av_frame_alloc();
if( !frame ) {
- fprintf(stderr, "FFMPEG::scan: av_frame_alloc failed\n");
+ fprintf(stderr,"FFMPEG::scan: ");
+ fprintf(stderr,_("av_frame_alloc failed\n"));
return -1;
}
AVStream *st = fmt_ctx->streams[i];
AVCodecID codec_id = st->codec->codec_id;
AVCodec *decoder = avcodec_find_decoder(codec_id);
- if( avcodec_open2(st->codec, decoder, &copts) < 0 )
- fprintf(stderr, "FFMPEG::scan: codec open failed\n");
+ if( avcodec_open2(st->codec, decoder, &copts) < 0 ) {
+ fprintf(stderr,"FFMPEG::scan: ");
+ fprintf(stderr,_("codec open failed\n"));
+ }
av_dict_free(&copts);
}
int errs = 0;
if( ret < 0 ) {
if( ret == AVERROR_EOF ) break;
if( ++errs > 100 ) {
- ff_err(ret, "over 100 read_frame errs\n");
+ ff_err(ret,_("over 100 read_frame errs\n"));
break;
}
continue;
int got_frame = 0;
int ret = aud->decode_frame(&pkt, frame, got_frame);
if( ret <= 0 ) break;
- if( got_frame ) {
+ if( got_frame && frame->channels == nch ) {
float *samples;
int len = aud->get_samples(samples,
&frame->extended_data[0], frame->nb_samples);
void FFStream::load_markers(IndexMarks &marks, double rate)
{
- index_markers = &marks;
int in = 0;
int64_t sz = marks.size();
int max_entries = fmt_ctx->max_index_size / sizeof(AVIndexEntry) - 1;