Android9.0 Camera2 橫屏問題修改記錄

vendor\mediatek\proprietary\packages\apps 目錄下有三份相機源碼 分別是

Camera搁进、 Camera1入宦、 Camera2

通過查看 mk 發(fā)現(xiàn)通過 ifeq ($(MTK_CAMERA_APP_VERSION), 3) 來控制編譯哪一個震捣,

MTK_CAMERA_APP_VERSION 宏定義在 device/mediateksample/xxxxxx/ProjectConfig.mk

整體界面相關(guān)

Camera2 中適配了兩套 api瘪弓, 老版本的 Camera 和新版本的 Camera2, 通過 CameraApiHelper 配置

Camera2\common\src\com\mediatek\camera\common\mode\CameraApiHelper.java

public static CameraApi getCameraApiType(@Nullable String modeName) {
        return CameraApi.API2;
}

 public enum CameraApi {
        /** Use the {@link android.hardware.Camera} class. */
        API1,
        /** Use the {@link android.hardware.camera2} package. */
        API2
}

預(yù)覽布局不延伸到 navigation 中宰掉,不顯示 statusbar

增加 requestWindowFeature(Window.FEATURE_NO_TITLE)

Camera2\host\src\com\mediatek\camera\QuickActivity.java

@Override
    protected final void onCreate(Bundle bundle) {
        LogHelper.i(TAG, "onCreate()");
        IPerformanceProfile profile = PerformanceTracker.create(TAG, "onCreate").start();
        mStartupOnCreate = true;
        super.onCreate(bundle);

        //cczheng add for don't show statusbar
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        mMainHandler = new Handler(getMainLooper());
        onPermissionCreateTasks(bundle);
        profile.stop();
    }

注釋 setSystemUiVisibility(View.SYSTEM_UI_LAYOUT_FLAGS | View.SYSTEM_UI_FLAG_LAYOUT_STABLE

Camera2\host\src\com\mediatek\camera\CameraActivity.java

@Override
    protected void onCreateTasks(Bundle savedInstanceState) {
        if (!isThirdPartyIntent(this) && !isOpenFront(this)) {
            CameraUtil.launchCamera(this);
        }
        IPerformanceProfile profile = PerformanceTracker.create(TAG, "onCreate").start();
        super.onCreateTasks(savedInstanceState);

        //cczheng annotation for layout forbbiden into navigationbar area
        /*getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_LAYOUT_FLAGS
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);*/

        setContentView(R.layout.activity_main);
        mOrientationListener = new OrientationEventListenerImpl(this);
        //create common ui module.
        mCameraAppUI = new CameraAppUI(this);
        profile.mark("CameraAppUI initialized.");
        mCameraAppUI.onCreate();
        profile.mark("CameraAppUI.onCreate done.");
        mIModeListener = new ModeManager();
        mIModeListener.create(this);
        profile.mark("ModeManager.create done.");
        profile.stop();
    }

旋轉(zhuǎn)界面圓形圖標(biāo) 90 度, 閃光燈恐仑、HDR灰署、拍照模式等

canvas.rotate(90)

Camera2\common\src\com\mediatek\camera\common\widget\RotateImageView.java

 @Override
    protected void onDraw(Canvas canvas) {
        Drawable drawable = getDrawable();

        if (drawable == null) {
            return;
        }

        Rect bounds = drawable.getBounds();
        int w = bounds.right - bounds.left;
        int h = bounds.bottom - bounds.top;

        ....

         // canvas.rotate(-mCurrentDegree);
        canvas.rotate(90);//cczheng change 90 for rotate all imageView
        canvas.translate(-w / 2, -h / 2);
        if (mDrawableBitmap != null) {
            canvas.drawBitmap(mDrawableBitmap, 0, 0, null);
        } else {
            drawable.draw(canvas);
        }
        canvas.restoreToCount(saveCount);
    }


拍照相關(guān)

預(yù)覽旋轉(zhuǎn) 90

horizontalMirrorData() 和 changePreviewDisplayOrientation() 都是從網(wǎng)上找的簡單矩陣算法判帮,驗證了還真的能達到效果

鏡像的問題底層驅(qū)動修改了,app 就不用處理了

預(yù)覽旋轉(zhuǎn)角度溉箕,根據(jù)實際情況我注釋了 postScale(),這樣導(dǎo)致了橫屏被拉伸了晦墙,人臉變胖了,只需要單純的 postRotate(90) 即可

Camera2\host\src\com\mediatek\camera\ui\preview\TextureViewController.java


//用于水平翻轉(zhuǎn)鏡像
private void horizontalMirrorData(){
        LogHelper.d(TAG, "updatePreviewSize horizontalMirrorData()");
        Matrix matrix = mTextureView.getTransform(new Matrix());
        matrix.setScale(-1, 1);
        int width = mTextureView.getWidth();
        matrix.postTranslate(width, 0);
        mTextureView.setTransform(matrix);
}

//用于旋轉(zhuǎn)預(yù)覽角度
private void changePreviewDisplayOrientation() {
        int mTextureViewWidth = mTextureView.getWidth();
        int mTextureViewHeight = mTextureView.getHeight();

        int rotation = mApp.getActivity().getWindowManager().getDefaultDisplay().getRotation();
        LogHelper.d(TAG,"rotation="+rotation);
        LogHelper.e(TAG,"mPreviewWidth="+mPreviewWidth+" mPreviewHeight="+mPreviewHeight);
        LogHelper.e(TAG,"textureWidth="+mTextureViewWidth+" textureHeight="+mTextureViewHeight);

        Matrix matrix = new Matrix();
        RectF viewRect = new RectF(0, 0, mTextureViewWidth, mTextureViewHeight);
        RectF bufferRect = new RectF(0, 0, mPreviewHeight, mPreviewWidth);
        float centerX = viewRect.centerX();
        float centerY = viewRect.centerY();
        if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
            LogHelper.e(TAG,"Surface.ROTATION_90 ROTATION_270");
            /*bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
            matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
            float scale = Math.max((float) mTextureViewHeight / mPreviewHeight,
                                    (float) mTextureViewWidth / mPreviewWidth);
            LogHelper.d(TAG,"scale="+scale);
            matrix.postScale(scale, scale, centerX, centerY);*/
            matrix.postRotate((90 * (rotation - 2)) % 360, centerX, centerY);
        } else if (Surface.ROTATION_180 == rotation) {
            LogHelper.d(TAG,"Surface.ROTATION_180 =");
            matrix.postRotate(180, centerX, centerY);
        }
        mTextureView.setTransform(matrix);
}


private class SurfaceChangeCallback implements TextureView.SurfaceTextureListener {
        private ISurfaceStatusListener mListener;

        .....

        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            //cczheng add for mirror preview data
            //horizontalMirrorData();
            changePreviewDisplayOrientation();

            mIsSurfaceCreated = true;
            surface.setDefaultBufferSize(mPreviewWidth, mPreviewHeight);
            if (mListener != null) {
                mListener.surfaceChanged(surface, mPreviewWidth, mPreviewHeight);
            }
            LogHelper.d(TAG, "onSurfaceTextureAvailable surface  = " + surface +
             " width " + width + " height " + height);
        }
    
        .....
}

人臉框位置相關(guān)

因為旋轉(zhuǎn)了屏幕方向肴茄,人臉框的坐標(biāo)位置就不對了晌畅,需要調(diào)整為正確的

通過分析打印日志發(fā)現(xiàn)

CamAp_FaceViewCtrl: [updateFacesViewByFace] new face num = 1, clear hide msg, show view right now

CamAp_FaceViewCtrl: [updateFacesViewByFace] new face num = 1, clear hide msg, send hide msg delay 1500 ms

和人臉框相關(guān)的類有以下幾個

Camera2\feature\setting\facedetection\src\com\mediatek\camera\feature\setting\facedetection\FaceViewCtrl.java

Camera2\feature\setting\facedetection\src\com\mediatek\camera\feature\setting\facedetection\FaceView.java

Camera2\common\src\com\mediatek\camera\common\utils\CoordinatesTransform.java

FaceViewCtrl 控制顯示隱藏, FaceView 繪制人臉框(其實是 ic_face_detection_focusing.9.png 圖片)寡痰,CoordinatesTransform 轉(zhuǎn)換人臉坐標(biāo)

看到上面打印的日志踩麦,人臉框顯示 1.5 s 后會自動隱藏,這應(yīng)該是 MTK 當(dāng)時遺留的一個 bug

為了讓人臉框一直顯示氓癌,注釋 updateFacesViewByFace() 中的 MSG_FACE_VIEW_HIDE 消息發(fā)送


private void updateFacesViewByFace(Face[] faces) {
        if (!mIsEnable) {
            LogHelper.e(TAG, "[updateFacesViewByFace] mIsEnable is false, ignore this time");
            return;
        }
        if (faces != null && faces.length > 0
                && mFaceViewState == FaceViewState.STATE_INIT) {
            // Check if face view has really been shown, if not , not hide view this time.
            // Why to do this check?
            // Maybe higher priority view is shown when face view wants to show, after higher
            // priority view is not shown, maybe face num is not changed too, it's time to hide
            // face view. So face view has no chance to show out.
            if (mHideViewWhenFaceCountNotChange && faces.length == mFaceNum
                    && mFaceView.hasReallyShown()) {
                // if face view is hide now, not send message, only update wait state
                if (mFaceView.getVisibility() != View.VISIBLE) {
                    mMainHandler.removeMessages(MSG_FACE_VIEW_HIDE);
                    mWaitFocusState = WaitFocusState.WAIT_NOTHING;
                } else if (!mMainHandler.hasMessages(MSG_FACE_VIEW_HIDE)) {
                    // if there is not hide msg in queue, send delay message to hide

                    //cczheng annotation don't auto hide faceview 1.5s
                    /*mMainHandler.removeMessages(MSG_FACE_VIEW_HIDE);
                    LogHelper.e(TAG, "[updateFacesViewByFace] new face num = " + faces.length +
                            ", clear hide msg, send hide msg delay "
                            + HIDE_VIEW_TIMEOUT_WAIT_AF_SCAN + " ms");
                    mMainHandler.sendEmptyMessageDelayed(MSG_FACE_VIEW_HIDE,
                            HIDE_VIEW_TIMEOUT_WAIT_AF_SCAN);*/
                }
            } else {
                LogHelper.e(TAG, "[updateFacesViewByFace] new face num = " + faces.length +
                        ", clear hide msg, show view right now");
                mMainHandler.removeMessages(MSG_FACE_VIEW_HIDE);
                mWaitFocusState = WaitFocusState.WAIT_PASSIVE_SCAN;
                showView();
                mFaceView.resetReallyShown();
            }

            mFaceView.setFaces(faces);
            mFaceNum = faces.length;
        }
    }

FaceView 中的 onDraw() 通過遍歷人臉集合谓谦,繪制人臉框,mFaceIndicator 就是上面說的 .9 圖片贪婉,來看下坐標(biāo)的計算方法

@Override
    protected void onDraw(Canvas canvas) {
        LogHelper.i(TAG, "[FaceView onDraw]");
        mReallyShown = true;
        if (mFaces != null && mFaces.length > 0) {
            for (int i = 0; i < mFaces.length; i++) {
                Rect rect = CoordinatesTransform.normalizedPreviewToUi(mFaces[i].rect,
                        mPreviewWidth, mPreviewHeight,
                        mDisplayOrientation, mMirror);
                mFaceIndicator.setBounds(rect.left, rect.top,
                        rect.right, rect.bottom);
                mFaceIndicator.draw(canvas);
            }
        }
        super.onDraw(canvas);
    }

通過傳遞原始的人臉坐標(biāo)反粥,和當(dāng)前實際預(yù)覽的畫布寬高,是否鏡像進行計算,

最終通過修改 displayOrientation 為 90疲迂,viewWidth 和 viewHeight 由原來的 / 2000f 修改為 /2200f 和 /1500f

當(dāng)然也可能需要根據(jù)你的屏幕實際尺寸調(diào)整

public static Rect normalizedPreviewToUi(Rect rect, int w, int h,
                                      int displayOrientation, boolean isMirror) {
        int previewHeight = 0;
        int previewWidth = 0;

        if (displayOrientation == 0 || displayOrientation == 180) {
            previewHeight = h > w ? w : h;//740
            previewWidth = h > w ? h : w;//986
        } else if (displayOrientation == 90 || displayOrientation == 270) {
            previewHeight = h > w ? h : w;//986
            previewWidth = h > w ? w : h;//740
        }
        coordinatesLog(TAG, "normalizedPreviewToUi, w = " + w + ", h = " + h
                + ", orientation = " + displayOrientation
                + ", mirror = " + isMirror);
        coordinatesLog(TAG, "normalizedPreviewToUi, previewWidth = " + previewWidth 
            + ", previewHeight = " + previewHeight);
        coordinatesLog(TAG, "normalizedPreviewToUi, rect = (" + rect.left + ", " + rect.top + ", "
                + rect.right + ", " + rect.bottom + ")");
        Matrix matrix = new Matrix();
        prepareMatrix(matrix, isMirror, displayOrientation, previewWidth, previewHeight);
        RectF rectf = new RectF(rect);
        matrix.mapRect(rectf);
        Rect resultRect = new Rect();
        rectf.round(resultRect);
        coordinatesLog(TAG, "normalizedPreviewToUi, result_rect = (" + resultRect.left + ", "
                + resultRect.top + ", "
                + resultRect.right + ", " + resultRect.bottom + ")");
        return resultRect;
    }

private static void prepareMatrix(Matrix matrix, boolean mirror, int displayOrientation,
                                      int viewWidth, int viewHeight) {
        // Need mirror for front camera.
        matrix.setScale(mirror ? -1 : 1, 1);
        // This is the value for android.hardware.Camera.setDisplayOrientation.
        matrix.postRotate(90 /*displayOrientation*/);
        // Camera driver coordinates range from (-1000, -1000) to (1000, 1000).
        // UI coordinates range from (0, 0) to (width, height).
        // matrix.postScale(viewWidth / 2000f, viewHeight / 2000f);
        //cczheng change displayOrientation 0 to 90, scale 2000->2200 2000->1500
        matrix.postScale(viewWidth / 2200f, viewHeight / 1500f);
        matrix.postTranslate(viewWidth / 2f, viewHeight / 2f);
    }

錄像相關(guān)

經(jīng)過上面的調(diào)整才顿,錄像預(yù)覽時方向是對的,但保存的視頻播放時依舊是豎屏的尤蒿,這么說我們還需要進一步修改郑气。

通過搜索發(fā)現(xiàn)設(shè)置錄像參數(shù)時 mMediaRecorder.setOrientationHint() 就是控制保存視頻的成像方向。

整個工程搜索找到

./common/src/com/mediatek/camera/common/mode/video/recorder/NormalRecorder.java:        mMediaRecorder.setOrientationHint(spec.orientationHint);

通過打印日志發(fā)現(xiàn) orientationHint 果然為 0,豎屏腰池,那么我們只需將 orientationHint 改為 90 應(yīng)該就能為橫屏

2019-11-21 08:30:09.601 3937-3937/com.mediatek.camera D/CamAp_VideoHelper: [getVideoTempPath] mTempPath = /storage/emulated/0/DCIM/Camera/.videorecorder.3gp.tmp
2019-11-21 08:30:09.648 3937-3937/com.mediatek.camera D/CamAp_NormalRecorder: [init]   filePath = /storage/emulated/0/DCIM/Camera/.videorecorder.3gp.tmp  spec.captureRate = 0  spec.videoFrameRate = 0  spec.orientationHint = 0  spec.profile.videoFrameRate = 30  spec.profile.videoFrameWidth = 1280  spec.profile.videoFrameHeight = 720

接下來簡單跟蹤下初始化配置參數(shù)的過程

common\src\com\mediatek\camera\common\mode\video\VideoMode.java

initRecorder() 創(chuàng)建 NormalRecorder 對象尾组,并開始初始化 init,需要傳遞 RecorderSpec 對象(包含很多錄像相關(guān)參數(shù)的 bean)

通過自身 configRecorderSpec() 創(chuàng)建示弓,最終調(diào)用到 VideoHelper 的 configRecorderSpec()

protected boolean initRecorder(boolean isStartRecording) {
        LogHelper.d(TAG, "[initRecorder]");
        releaseRecorder();
        mRecorder = new NormalRecorder();
        try {
            mRecorder.init(configRecorderSpec(isStartRecording));
            setMediaRecorderParameters();
            initForHal3(isStartRecording);
        } catch (RuntimeException e) {
            e.printStackTrace();
            releaseRecorder();
            return false;
        }
        return true;
    }

private IRecorder.RecorderSpec configRecorderSpec(boolean isStartRecording) {
        IRecorder.RecorderSpec recorderSpec = mVideoHelper.configRecorderSpec(
                getProfile(), mCameraId, mCameraApi, mSettingManager);
        mOrientationHint = recorderSpec.orientationHint;
        recorderSpec.infoListener = mOnInfoListener;
        recorderSpec.errorListener = mOnErrorListener;
        recorderSpec.releaseListener = mOnInfoListener;
        recorderSpec = modifyRecorderSpec(recorderSpec, isStartRecording);
        return recorderSpec;
    }

configRecorderSpec() 中新建一個內(nèi)部類對象 RecorderSpec讳侨,依次給各個 public 字段賦值,默認指定使用 CameraApi.API2

所以獲取 orientationHint 走的如下帶 CameraCharacteristics 參數(shù)的 getRecordingRotation() 方法

由于我們的設(shè)備沒有重力傳感器奏属,mApp.getGSensorOrientation() 一直是 -1跨跨,也就是 ORIENTATION_UNKNOWN

所以最終 rotation = sensorOrientation,打印 sensorOrientation 為 0囱皿,也就符合上面說的 orientationHint 果然為 0

當(dāng)然你也可以在這里修改 getRecordingRotation() 返回值也能達到一樣的效果

common\src\com\mediatek\camera\common\mode\video\VideoHelper.java

public IRecorder.RecorderSpec configRecorderSpec(CamcorderProfile profile, String cameraId,
                CameraDeviceManagerFactory.CameraApi api, ISettingManager settingManager) {
        sProfile = profile;
        IRecorder.RecorderSpec recorderSpec = new IRecorder.RecorderSpec();
        if (mCameraDevice.getCamera() != null) {
            mCameraDevice.unLockCamera();
            recorderSpec.camera = mCameraDevice.getCamera().getCamera();
        }
        if (api == CameraDeviceManagerFactory.CameraApi.API1) {
            recorderSpec.videoSource = MediaRecorder.VideoSource.CAMERA;
            recorderSpec.orientationHint = getRecordingRotation(mApp.getGSensorOrientation(),
                    mCameraDevice.getCameraInfo(Integer.parseInt(cameraId)));
        } else {
            recorderSpec.videoSource = MediaRecorder.VideoSource.SURFACE;
            recorderSpec.orientationHint = getRecordingRotation(mApp.getGSensorOrientation(),
                    getCameraCharacteristics(mApp.getActivity(), cameraId));
        }
        if (VALUE_ON.equals(settingManager.getSettingController().queryValue("key_microphone"))) {
            recorderSpec.isRecordAudio = true;
            recorderSpec.audioSource = MediaRecorder.AudioSource.CAMCORDER;
        } else {
            recorderSpec.isRecordAudio = false;
        }
        recorderSpec.profile = sProfile;
        recorderSpec.maxDurationMs = 0;
        recorderSpec.maxFileSizeBytes = getRecorderMaxSize();
        recorderSpec.location = mCameraContext.getLocation();
        recorderSpec.outFilePath = getVideoTempPath();
        return recorderSpec;
    }

public static int getRecordingRotation(int orientation, CameraCharacteristics characteristics) {
        int rotation = -1;
        int sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
        boolean facingFront = characteristics.get(CameraCharacteristics.LENS_FACING)
                == CameraCharacteristics.LENS_FACING_FRONT;
        if (orientation != OrientationEventListener.ORIENTATION_UNKNOWN) {
            if (facingFront) {
                rotation = (sensorOrientation - orientation + 360) % 360;
            } else {
                rotation = (sensorOrientation + orientation) % 360;
            }
        } else {
            rotation = sensorOrientation;
        }
        LogHelper.e(TAG, "[getRecordingRotation] orientation = " +
                orientation + " sensorOrientation = " + sensorOrientation + " rotation = "  + rotation);
        return rotation;
    }

APP 應(yīng)用參考文章

Android Camera2 API和拍照與錄像過程

Android Camera2教程之打開相機勇婴、開啟預(yù)覽忱嘹、實現(xiàn)PreviewCallback、拍照

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末耕渴,一起剝皮案震驚了整個濱河市德谅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌萨螺,老刑警劉巖窄做,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異慰技,居然都是意外死亡椭盏,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門吻商,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掏颊,“玉大人,你說我怎么就攤上這事艾帐∥谝叮” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵柒爸,是天一觀的道長准浴。 經(jīng)常有香客問我,道長捎稚,這世上最難降的妖魔是什么乐横? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮今野,結(jié)果婚禮上葡公,老公的妹妹穿的比我還像新娘。我一直安慰自己条霜,他們只是感情好催什,可當(dāng)我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宰睡,像睡著了一般蒲凶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上夹厌,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天豹爹,我揣著相機與錄音裆悄,去河邊找鬼矛纹。 笑死,一個胖子當(dāng)著我的面吹牛光稼,可吹牛的內(nèi)容都是我干的或南。 我是一名探鬼主播孩等,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼采够!你這毒婦竟也來了肄方?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蹬癌,失蹤者是張志新(化名)和其女友劉穎权她,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逝薪,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡隅要,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了董济。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片步清。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖虏肾,靈堂內(nèi)的尸體忽然破棺而出廓啊,到底是詐尸還是另有隱情,我是刑警寧澤封豪,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布谴轮,位于F島的核電站,受9級特大地震影響吹埠,放射性物質(zhì)發(fā)生泄漏书聚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一藻雌、第九天 我趴在偏房一處隱蔽的房頂上張望雌续。 院中可真熱鬧,春花似錦胯杭、人聲如沸驯杜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸽心。三九已至,卻和暖如春居暖,著一層夾襖步出監(jiān)牢的瞬間顽频,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工太闺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留糯景,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像蟀淮,于是被迫代替她去往敵國和親最住。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容