ios - Cutting MPEG-TS file via ffmpegwrapper? -


i have mpeg-ts files on device. cut fairly-exact time off start of files on-device.

using ffmpegwrapper base, i'm hoping achieve this.

i'm little lost on c api of ffmpeg, however. start?

i tried dropping packets prior start pts looking for, broke video stream.

    packet->pts = av_rescale_q(packet->pts, inputstream.stream->time_base, outputstream.stream->time_base);     packet->dts = av_rescale_q(packet->dts, inputstream.stream->time_base, outputstream.stream->time_base);      if(startpts == 0){         startpts = packet->pts;     }      if(packet->pts < cuttimestartpts + startpts){         av_free_packet(packet);         continue;     } 

how cut off part of start of input file without destroying video stream? when played back, want 2 cut segments run seamlessly together.

ffmpeg -i time.ts -c:v libx264 -c:a copy -ss $cut_point -map 0 -y after.ts ffmpeg -i time.ts -c:v libx264 -c:a copy -to $cut_point -map 0 -y before.ts 

seems need. think re-encode needed video can start @ arbitrary point , not existing keyframe. if there's more efficient solution, that's great. if not, enough.

edit: here's attempt. i'm cobbling various pieces don't understand copied here. i'm leaving off "cutting" piece try , audio + video encoded written without layering complexity. exc_bad_access on avcodec_encode_video2(...)

- (void)convertinputpath:(nsstring *)inputpath outputpath:(nsstring *)outputpath                  options:(nsdictionary *)options progressblock:(ffmpegwrapperprogressblock)progressblock          completionblock:(ffmpegwrappercompletionblock)completionblock {     dispatch_async(conversionqueue, ^{         ffinputfile *inputfile = nil;         ffoutputfile *outputfile = nil;         nserror *error = nil;          inputfile = [[ffinputfile alloc] initwithpath:inputpath options:options];         outputfile = [[ffoutputfile alloc] initwithpath:outputpath options:options];          [self setupdirectstreamcopyfrominputfile:inputfile outputfile:outputfile];         if (![outputfile openfileforwritingwitherror:&error]) {             [self finishwithsuccess:no error:error completionblock:completionblock];             return;         }         if (![outputfile writeheaderwitherror:&error]) {             [self finishwithsuccess:no error:error completionblock:completionblock];             return;         }          avrational default_timebase;         default_timebase.num = 1;         default_timebase.den = av_time_base;         ffstream *outputvideostream = outputfile.streams[0];         ffstream *inputvideostream = inputfile.streams[0];          avframe *frame;         avpacket inpacket, outpacket;          frame = avcodec_alloc_frame();         av_init_packet(&inpacket);          while (av_read_frame(inputfile.formatcontext, &inpacket) >= 0) {             if (inpacket.stream_index == 0) {                 int framefinished;                 avcodec_decode_video2(inputvideostream.stream->codec, frame, &framefinished, &inpacket); //                if (framefinished && frame->pkt_pts >= starttime_int64 && frame->pkt_pts <= endtime_int64) {                 if (framefinished){                     av_init_packet(&outpacket);                     int output;                     avcodec_encode_video2(outputvideostream.stream->codec, &outpacket, frame, &output);                     if (output) {                         if (av_write_frame(outputfile.formatcontext, &outpacket) != 0) {                             fprintf(stderr, "convert(): error while writing video frame\n");                             [self finishwithsuccess:no error:nil completionblock:completionblock];                         }                     }                     av_free_packet(&outpacket);                 }                 if (frame->pkt_pts > endtime_int64) {                     break;                 }             }         }         av_free_packet(&inpacket);          if (![outputfile writetrailerwitherror:&error]) {             [self finishwithsuccess:no error:error completionblock:completionblock];             return;         }          [self finishwithsuccess:yes error:nil completionblock:completionblock];     }); } 

the ffmpeg (libavformat/codec, in case) api maps ffmpeg.exe commandline arguments pretty closely. open file, use avformat_open_input_file(). last 2 arguments can null. fills in avformatcontext you. start reading frames using av_read_frame() in loop. pkt.stream_index tell stream each packet belongs to, , avformatcontext->streams[pkt.stream_index] accompanying stream information, tells codec uses, whether it's video/audio, etc. use avformat_close() shut down.

for muxing, use inverse, see muxing details. it's allocate, avio_open2, add streams each existing stream in input file (basically context->streams[]), avformat_write_header(), av_interleaved_write_frame() in loop, av_write_trailer() shut down (and free allocated context in end).

encoding/decoding of video stream(s) done using libavcodec. each avpacket muxer, use avcodec_decode_video2(). use avcodec_encode_video2() encoding of output avframe. note both introduce delay first few calls each function not return data , need flush cached data calling each function null input data tail packets/frames out of it. av_interleave_write_frame interleave packets correctly video/audio stream not desync (as in: video packets of same timestamp occur mbs after audio packets in ts file).

if need more detailed examples avcodec_decode_video2, avcodec_encode_video2, av_read_frame or av_interleaved_write_frame, google "$function example" , you'll see full-fledged examples showing how use them correctly. x264 encoding, set default parameters in avcodeccontext when calling avcodec_open2 encoding quality settings. in c api, using avdictionary, e.g.:

avdictionary opts = *null; av_dict_set(&opts, "preset", "veryslow", 0); // use either crf or b, not both! see link above on h264 encoding options av_dict_set_int(&opts, "b", 1000, 0); av_dict_set_int(&opts, "crf", 10, 0); 

[edit] oh forgot 1 part, timestamping. each avpacket , avframe has pts variable in struct, , can use decide whether include packet/frame in output stream. audio, you'd use avpacket.pts demuxing step delimiter, , video, you'd use avframe.pts decoding step delimited. respective documentation tells in unit are.

[edit2] see you're still having issues without actual code, here's real (working) transcoder re-codes video , re-muxes audio. has tons of bugs, leaks , lacks proper error reporting, doesn't deal timestamps (i'm leaving exercise), basic things asked for:

#include <stdio.h> #include <libavformat/avformat.h> #include <libavcodec/avcodec.h>  static avformatcontext *inctx, *outctx; #define max_streams 16 static avcodeccontext *inavctx[max_streams]; static avcodeccontext *outavctx[max_streams];  static int openinputfile(const char *file) {     int res;      inctx = null;     res = avformat_open_input(& inctx, file, null, null);     if (res != 0)         return res;     res = avformat_find_stream_info(inctx, null);     if (res < 0)         return res;      return 0; }  static void closeinputfile(void) {     int n;      (n = 0; n < inctx->nb_streams; n++)         if (inavctx[n]) {             avcodec_close(inavctx[n]);             avcodec_free_context(&inavctx[n]);         }      avformat_close_input(&inctx); }  static int openoutputfile(const char *file) {     int res, n;      outctx = avformat_alloc_context();     outctx->oformat = av_guess_format(null, file, null);     if ((res = avio_open2(&outctx->pb, file, avio_flag_write, null, null)) < 0)         return res;      (n = 0; n < inctx->nb_streams; n++) {         avstream *inst = inctx->streams[n];         avcodeccontext *inc = inst->codec;          if (inc->codec_type == avmedia_type_video) {             // video decoder             inavctx[n] = avcodec_alloc_context3(inc->codec);             avcodec_copy_context(inavctx[n], inc);             if ((res = avcodec_open2(inavctx[n], avcodec_find_decoder(inc->codec_id), null)) < 0)                 return res;              // video encoder             avcodec *encoder = avcodec_find_encoder_by_name("libx264");             avstream *outst = avformat_new_stream(outctx, encoder);             outst->codec->width = inavctx[n]->width;             outst->codec->height = inavctx[n]->height;             outst->codec->pix_fmt = inavctx[n]->pix_fmt;             avdictionary *dict = null;             av_dict_set(&dict, "preset", "veryslow", 0);             av_dict_set_int(&dict, "crf", 10, 0);             outavctx[n] = avcodec_alloc_context3(encoder);             avcodec_copy_context(outavctx[n], outst->codec);             if ((res = avcodec_open2(outavctx[n], encoder, &dict)) < 0)                 return res;         } else if (inc->codec_type == avmedia_type_audio) {             avformat_new_stream(outctx, inc->codec);             inavctx[n] = outavctx[n] = null;         } else {             fprintf(stderr, "don’t know stream %d\n", n);             return -1;         }     }      if ((res = avformat_write_header(outctx, null)) < 0)         return res;      return 0; }  static void closeoutputfile(void) {     int n;      av_write_trailer(outctx);     (n = 0; n < outctx->nb_streams; n++)         if (outctx->streams[n]->codec)             avcodec_close(outctx->streams[n]->codec);     avformat_free_context(outctx); }  static int encodeframe(int stream_index, avframe *frame, int *gotoutput) {     avpacket outpacket;     int res;      av_init_packet(&outpacket);     if ((res = avcodec_encode_video2(outavctx[stream_index], &outpacket, frame, gotoutput)) < 0) {         fprintf(stderr, "failed encode frame\n");         return res;     }     if (*gotoutput) {         outpacket.stream_index = stream_index;         if ((res = av_interleaved_write_frame(outctx, &outpacket)) < 0) {             fprintf(stderr, "failed write packet\n");             return res;         }     }     av_free_packet(&outpacket);      return 0; }  static int decodepacket(int stream_index, avpacket *pkt, avframe *frame, int *framefinished) {     int res;      if ((res = avcodec_decode_video2(inavctx[stream_index], frame,                                      framefinished, pkt)) < 0) {         fprintf(stderr, "failed decode frame\n");         return res;     }     if (*framefinished){         int hasoutput;          frame->pts = frame->pkt_pts;         return encodeframe(stream_index, frame, &hasoutput);     } else {         return 0;     } }  int main(int argc, char *argv[]) {     char *input = argv[1];     char *output = argv[2];     int res, n;      printf("converting %s %s\n", input, output);     av_register_all();     if ((res = openinputfile(input)) < 0) {         fprintf(stderr, "failed open input file %s\n", input);         return res;     }     if ((res = openoutputfile(output)) < 0) {         fprintf(stderr, "failed open output file %s\n", input);         return res;     }      avframe *frame = av_frame_alloc();     avpacket inpacket;      av_init_packet(&inpacket);     while (av_read_frame(inctx, &inpacket) >= 0) {         if (inavctx[inpacket.stream_index] != null) {             int framefinished;             if ((res = decodepacket(inpacket.stream_index, &inpacket, frame, &framefinished)) < 0) {                 return res;             }         } else {             if ((res = av_interleaved_write_frame(outctx, &inpacket)) < 0) {                 fprintf(stderr, "failed write packet\n");                 return res;             }         }     }      (n = 0; n < inctx->nb_streams; n++) {         if (inavctx[n]) {             // flush decoder             int framefinished;             {                 inpacket.data = null;                 inpacket.size = 0;                 if ((res = decodepacket(n, &inpacket, frame, &framefinished)) < 0)                     return res;             } while (framefinished);              // flush encoder             int gotoutput;             {                 if ((res = encodeframe(n, null, &gotoutput)) < 0)                     return res;             } while (gotoutput);         }     }     av_free_packet(&inpacket);      closeinputfile();     closeoutputfile();      return 0; } 

Comments

Popular posts from this blog

c++ - llvm function pass ReplaceInstWithInst malloc -

Cross-Compiling Linux Kernel for Raspberry Pi - ${CCPREFIX}gcc -v does not work -

java.lang.NoClassDefFoundError When Creating New Android Project -